我需要返回表格位置中每个设备的最后一行
我的表名是:位置
+------------+----------+--------------+--------------+----------+
| 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。
感谢,
伊万德罗
答案 0 :(得分: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个Location项的List - 最后一行,这将是一个空列表。
如果要一次性为所有设备选择最新位置,可以使用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 doesn't permit using subqueries in the FROM clause,所以尽管我选择这样做,但只能使用原生查询功能,这样使用起来会更加不方便。
顺便说一下,在我看来,像你一样存储时间戳是一种不好的做法。它没有适当的可索引性,在查询和订购时会给您带来麻烦,只是一场普通的噩梦。我会认真重新考虑你的架构的这一部分。
答案 1 :(得分: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();
现在,我需要查询从所有设备中选择最后一个位置:)
答案 2 :(得分:0)
试试这个
select top (1) location from location where deviceid=:deviceid
order by dateregistro,horaregistro desc
答案 3 :(得分:0)
这样的事情怎么样:
SELECT locationId
FROM location
WHERE dateregistro + horaregistro = (SELECT MAX(datergistro + horaregistro)
FROM location
WHERE deviceid = :deviceid)
AND deviceid = :deviceid
我不确定日期计算的正确性,但也许您可以创建一个新列,其中合并日期和时间。
答案 4 :(得分: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添加索引。
此外,我建议您重新考虑您的数据模型,因为此查询需要构建笛卡尔积(随着数据的增长,速度会相当快)
答案 5 :(得分: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)
答案 6 :(得分: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();
你可以使用类似的东西。对不起,在我的情况下,我将它用于设备目的。对不起,我知道为时已晚,但它可以帮助某人,如果有人先前回复,我会再次感到抱歉。谢谢