我有一个表定义为:
create table Foo (
X integer,
Y timestamp,
Z varchar(255),
primary key (X, Y)
);
对于给定的X,我想找到最近的行。到目前为止,我已经提出了以下内容,但是想知道是否有人知道哪些内容会表现更好或者只是“有趣”,例如使用左连接本身(我无法开始工作) )。
select * from Foo where X=1234 order by Y desc limit 0,1;
select * from Foo where X=1234 and Y in (select max(Y) from Foo where X=1234);
谢谢!
答案 0 :(得分:2)
您的第二个解决方案可行,但性能可能不是最佳的,并且可能会返回多行。您还应该将IN
更改为=
:
SELECT * FROM Foo
WHERE X = 1234 AND Y = (SELECT MAX(Y) FROM Foo WHERE X = 1234)
我认为第一个解决方案更好:
SELECT *
FROM Foo
WHERE X = 1234
ORDER BY Y DESC
LIMIT 1
在X,Y上添加索引以获得不错的表现。
答案 1 :(得分:2)
为每个用户(有事件)选择最近的行
select * from events e
join (select UserId, Max(time) time from events group by userId) t
ON (e.userId = t.userid and e.time = t.time)
答案 2 :(得分:1)
在第二个示例中,您使用的是相关子查询。您可以使用非相关子查询(派生表)。如果碰巧列出所有foos,这将更快,因为必须为外部查询的每一行调用一次相关的子查询。
这是使用派生表的示例:
SELECT foo.*
FROM foo
JOIN (
SELECT MAX(Y) max_time, X
FROM foo
GROUP BY X
) d_foo ON (d_foo.X = foo.X AND
d_foo.max_time = foo.Y);
测试用例:
INSERT INTO foo VALUES (1, '2010-01-01 12:00:00', '1');
INSERT INTO foo VALUES (1, '2010-01-03 12:00:00', '2');
INSERT INTO foo VALUES (2, '2010-01-05 12:00:00', '3');
INSERT INTO foo VALUES (2, '2010-01-02 12:00:00', '4');
INSERT INTO foo VALUES (3, '2010-01-08 12:00:00', '5');
INSERT INTO foo VALUES (4, '2010-01-03 12:00:00', '6');
INSERT INTO foo VALUES (4, '2010-01-04 12:00:00', '7');
结果:
+---+---------------------+------+
| X | Y | Z |
+---+---------------------+------+
| 1 | 2010-01-03 12:00:00 | 2 |
| 2 | 2010-01-05 12:00:00 | 3 |
| 3 | 2010-01-08 12:00:00 | 5 |
| 4 | 2010-01-04 12:00:00 | 7 |
+---+---------------------+------+
4 rows in set (0.02 sec)
但是,如果您始终将结果限制为仅X
,那么您的解决方案可能就好了。查看@Mark Byers' answer以获取有关此问题的进一步提示。
答案 3 :(得分:0)
以下是您将如何做到这一点:
SELECT *
FROM foo INNER JOIN (SELECT `x`, MAX(`y`) AS `y` FROM foo GROUP BY `x`) AS foo2 ON foo.x = foo2.x AND foo.y = foo2.y