MySQL按日期时间顺序选择不同的值

时间:2013-06-25 14:56:40

标签: mysql

(我不能说英语,但我会尽我所能)

我有两张桌子。

表1

id   carid    user
---------------------
1  |  A001 |   user1
2  |  A002 |   user1
3  |  A003 |   user2
4  |  A002 |   user3

表2

id  carid       datetime            lat       lon
----------------------------------------------------
1 | A001 | 2013-25-06 10:00:00 | -23.0000 | -46.0000
2 | A002 | 2013-25-06 10:01:00 | -24.3500 | -45.3200
3 | A002 | 2013-25-06 10:02:00 | -24.3800 | -45.3300
4 | A001 | 2013-25-06 10:05:00 | -23.0500 | -46.1000
5 | A003 | 2013-25-06 10:07:00 | -24.3500 | -45.3200
6 | A001 | 2013-25-06 10:10:00 | -23.0700 | -46.1200

我需要从datetime命令的“user1”中选择每个不同的注册表“carid”

我需要的结果:

   carid         datetime         lat       lon
--------------------------------------------------
   A001 |  2013-25-06 10:10:00 | -23.0700  |-46.1200
   A002 |  2013-25-06 10:02:00 | -24.3800  |-45.3300

我实际制作的方法是从我想要的用户中选择所有“carid”,然后通过.net单独选择每一行。

`SELECT carid FROM table1 where user = “user1”;`
carid
-----
A001
A002

然后选择我想要的行:

SELECT * FROM table2 WHERE car_id='A001' ORDER BY datetime DESC limit 1
SELECT * FROM table2 WHERE car_id='A002' ORDER BY datetime DESC limit 1

但是根据该用户的注册表“carid”的数量,我必须做很多查询。 我不知道是否可以用一个SELECT来改善我的工作方式,但这就是我的尝试:

SELECT car_id, datetime, lat, lon from table1 
INNER JOIN table2 on carid = car_id
WHERE user = 'user1'
GROUP BY carid
ORDER BY datetime DESC;

结果:

 carid    datetime            lat          lon
------------------------------------------------------
 A002 | 2013-25-06 10:01:00 | -24.3500 | -45.3200
 A001 | 2013-25-06 10:02:00 | -23.0000 | -46.0000

我也试过这个:

SELECT car_id, MAX(datetime) as datetime, lat, lon from table1 
INNER JOIN table2 on carid = car_id
WHERE user = 'user1'
GROUP BY carid
ORDER BY datetime DESC;

结果:

 carid     datetime            lat           lon
------------------------------------------------------
 A001 |  2013-25-06 10:10:00 | -23.0000 | -46.0000
 A002 |  2013-25-06 10:02:00 | -24.3500 | -45.3200

但我得到的结果是错误的。 如果没有选择所有行,我不知道该做什么,这比我真正做的那样慢。

有什么想法吗?

2 个答案:

答案 0 :(得分:6)

您可以加入table2两次,一次获得max(datetime) carId,第二次获得与latlon相关联的carId datetimeselect t1.carid, t2.datetime, t2.lat, t2.lon from table1 t1 inner join ( -- get the lat/lon associated with each carid and max datetime select t2.carid, t2.datetime, t2.lat, t2.lon from table2 t2 inner join ( -- get the max datetime for each carid select carid, max(datetime) datetime from table2 group by carid ) d on t2.carid = d.carid and t2.datetime = d.datetime ) t2 on t1.carid = t2.carid where user = 'user1';

max()

请参阅SQL Fiddle with Demo

您使用lat的查询返回了错误的loncarid值,因为您只是按{{1}}进行分组,因此MySQL可以任意选择列中的值不在聚合函数或GROUP BY中的选择列表。此行为归因于MySQL's Extensions to GROUP BY

来自MySQL文档:

  

MySQL扩展了GROUP BY的使用,因此选择列表可以引用GROUP BY子句中未命名的非聚合列。 ...您可以通过避免不必要的列排序和分组来使用此功能来获得更好的性能。但是,当GROUP BY中未命名的每个非聚合列中的所有值对于每个组都相同时,这非常有用。服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的。此外,添加ORDER BY子句不会影响每个组中值的选择。选择值后会对结果集进行排序,而ORDER BY不会影响服务器选择的值。

为了确保返回正确的值,您将需要使用与上面类似的子查询。

答案 1 :(得分:0)

我认为以下查询应该适用于您的方案。我没有尝试过,因为我没有数据。

SELECT
  t1.carid, t2.datetime, t2.lat, t2.lon
FROM
  table1 t1 JOIN table2 t2
  ON t1.carid = t2.carid AND t1.user='user1'
GROUP BY
  carid
HAVING
  t2.datetime=MAX(datetime);

让我知道这是否有效。