MySQL中给定用户的最新行

时间:2010-08-31 11:25:34

标签: sql mysql

我有一个表定义为:

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);

谢谢!

4 个答案:

答案 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