2

我需要在我的表格位置返回每个设备的最后一行

我的表名是:位置

+------------+----------+--------------+--------------+----------+  
| locationId | deviceId | dataRegistro | horaRegistro | location |  
+------------+----------+--------------+--------------+----------+  
|         50 |        1 |   2012-11-07 |     15:35:00 |      A12 |  
+------------+----------+--------------+--------------+----------+  
|         51 |        1 |   2012-11-07 |     15:37:40 |       B2 |  
+------------+----------+--------------+--------------+----------+  
|         52 |        2 |   2012-11-07 |     15:35:12 |       B8 |  
+------------+----------+--------------+--------------+----------+  
|         53 |        2 |   2012-11-07 |     15:35:40 |      50C |  
+------------+----------+--------------+--------------+----------+  
|         54 |        2 |   2012-11-07 |     15:40:00 |      94A |  
+------------+----------+--------------+--------------+----------+  

从我做的一个设备中选择最后一行

select L from Location L where deviceId = :deviceId order by "dataRegistro" DESC, "horaRegistro" DESC limit 1

现在如何选择每台设备的所有最新位置?:( 我使用 Java JPA。

谢谢,

埃万德罗

4

7 回答 7

5

如果 ID 是有序的,因此稍后记录的记录对应于较晚的日期,您可以使用此查询(我不会费心将字符串转换为日期,这会使其慢于可接受的速度。):

select L from Location L where deviceId = :deviceId order by L.locationId DESC 

并限制要在 Java 代码中返回的行数:

//EntityManager em; defined earlier
Query q = em.createQuery("select L from Location L where deviceId = :deviceId order by L.locationId DESC ");
q.setParameter("deviceId", "theDeviceIdIWantToQuery");
q.setMaxResults(1);
List<Location> results=query.getResultList();

如果给定的 deviceId 没有行,这将是一个空列表,或者一个包含 1 个位置项的列表 - 最后一个。

如果要一次性选择所有设备的最新位置,可以使用 IN 子句和子查询:

select L2 FROM Location L2 WHERE L2.locationId IN
    (select L.locationId from Location L 
    where L.deviceId = :deviceId 
    order by L.locationId DESC 
    group by L.deviceId)

遗憾的是,JPQL 不允许在 FROM 子句中使用子查询,所以虽然这是我的选择,但只能通过使用本机查询功能来实现,这使用起来更不方便。

顺便说一句,在我看来,像你这样存储时间戳是一种不好的做法。它不能正确索引,在查询和排序时会遇到麻烦,简直就是一场噩梦。我会认真重新考虑您架构的这一部分。

于 2012-11-08T13:44:22.803 回答
1

是的,我使用 JPA,这个例子只是为了演示我需要什么

我选择一台设备的JPA查询是

Query q = em.createQuery("select TL from TRKLocation TL where   
TL.device.deviceId = :deviceId and TL.msgError = '' order by 
TL.dataRegistro DESC, TL.horaRegistro DESC");
        q.setParameter("deviceId", deviceId);           
        q.setMaxResults(1);

list = q.getResultList();

现在,我需要查询以从所有设备中选择最后一个位置:)

于 2012-11-08T13:32:57.040 回答
0

像这样的东西怎么样:

SELECT locationId
  FROM location
 WHERE dateregistro + horaregistro = (SELECT MAX(datergistro + horaregistro)
                                        FROM location
                                       WHERE deviceid = :deviceid)
   AND deviceid = :deviceid

我不确定日期计算的正确性,但也许您可以创建一个新列,将日期和时间组合在一起。

于 2012-11-08T13:21:38.497 回答
0

如果 dateregistro 和 horaregistro 是字符串,您可以尝试以下查询:

select * from location l1
where dateregistro + horaregistro = (select max(dateregistro + horaregistro) from
location l2 where l2.deviceid = l1.deviceid)

更好的是,如果该locationid字段是唯一且已排序的键,则可以对其应用 where 条件:

select * from location l1
where locationid = (select max(locationid) from
location l2 where l2.deviceid = l1.deviceid)
于 2012-11-08T14:25:14.900 回答
0

我不明白你为什么不存储一个简单的时间戳,而不是为日期和时间设置两列。这使得运行您想要的选择变得更加困难。这是一个示例,如果时间戳可用,它应该如何工作(从查看 JPQL Spec 第 4.6.16 节这应该可以工作)

Select loc From Location loc where loc.ts_registered = 
(Select MAX(subloc.ts_registered) From Location subloc where subloc.deviceId = loc.deviceId)

我没有测试它,但我认为这应该有效。但请注意,此查询将在中型到大型数据集上运行得非常缓慢。您绝对应该为列 deviceId 添加索引。

此外,我建议您重新考虑您的数据模型,因为此查询需要构建笛卡尔积(随着数据的增长,这将很快变慢)

于 2012-11-08T14:06:47.857 回答
0

尝试这个

select top (1) location from location where deviceid=:deviceid 
 order by dateregistro,horaregistro desc
于 2012-11-08T13:15:29.953 回答
0
Query q= em.createQuery("Select D from DeviceInfo D WHERE D.devLastPing IN (SELECT MAX(DD.devLastPing) FROM DeviceInfo DD WHERE DD.devLastPing >= :startDate AND DD.devLastPing <= :endDate)");

        q.setParameter("startDate", startDate)
                .setParameter("endDate", endDate);
        List<DeviceInfo> list = (List<DeviceInfo>)q.getResultList();

你可以使用类似的东西。对不起,在我的情况下,我将它用于设备目的。抱歉,我知道为时已晚,但它可以帮助某人,如果有人之前回复过,再次抱歉。谢谢

于 2017-05-02T15:07:17.593 回答