MySQL中给定用户的最近一行

MySQL中给定用户的最近一行,sql,mysql,Sql,Mysql,我有一个表定义为: create table Foo ( X integer, Y timestamp, Z varchar(255), primary key (X, Y) ); 对于给定的X,我想找到最近的一行。到目前为止,我已经提出了以下内容,但我想知道是否有人知道一些性能更好的东西,或者只是“有趣”的东西,比如在自身上使用左连接(我还没有开始工作) 谢谢 第二个解决方案可以工作,但性能可能不是最优的,它可能返回多行。您还应将中的更改为=: SELECT

我有一个表定义为:

create table Foo (
    X integer,
    Y timestamp,
    Z varchar(255),
    primary key (X, Y)
);
对于给定的X,我想找到最近的一行。到目前为止,我已经提出了以下内容,但我想知道是否有人知道一些性能更好的东西,或者只是“有趣”的东西,比如在自身上使用左连接(我还没有开始工作)


谢谢

第二个解决方案可以工作,但性能可能不是最优的,它可能返回多行。您还应将中的
更改为
=

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上添加索引以获得良好的性能。

您的第二个解决方案可以工作,但性能可能不是最佳的,它可能返回多行。您还应将
中的
更改为
=

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上添加索引以获得良好的性能。

为每个用户(有事件的)选择最近的行


为每个用户(具有事件)选择最近的行


在第二个示例中,您使用的是一个相关子查询。您可以改用非相关子查询(派生表)。如果您碰巧列出了所有的foo,这将更快,因为对于外部查询的每一行,必须调用一个相关的子查询

这是一个使用派生表的示例:

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
,则您的解决方案可能很好。查看更多关于此的提示。

在第二个示例中,您使用的是相关子查询。您可以改用非相关子查询(派生表)。如果您碰巧列出了所有的foo,这将更快,因为对于外部查询的每一行,必须调用一个相关的子查询

这是一个使用派生表的示例:

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
,则您的解决方案可能很好。查看更多关于这方面的提示。

以下是您的操作方法:

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

以下是您将如何做到这一点:

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

列Y是否保证每个用户都是唯一的?一个用户中不可能有两个主键table@Mark拜尔斯:虽然Y很可能是唯一的,但不能保证,因为理论上两个条目可能有相同的时间戳。@老板:这是一个复合键-只要尝试在MySql中运行类似“descripe Foo”的东西,您就会看到它起作用。@Scruffer:但是由于复合主键,那么Y保证每个用户都是唯一的。Y列保证每个用户都是唯一的吗?在一个数据库中不可能有两个主键table@Mark拜尔斯:虽然Y很可能是唯一的,但不能保证,因为理论上两个条目可能有相同的时间戳。@boss:这是一个复合键-只要试着在MySql,你会看到它是有效的。@Scruffers:但是因为这个复合主键,所以Y保证每个用户都是唯一的。我认为这不正确。“select userId,max(time)”可能返回一个与表中主键不对应的值,即它可能给用户id 1,用户id为2的最大时间。@Scruffer,“主键”和“分组依据”在这里有什么关系??“时间”字段是否是主键的一部分并不重要。我想我在您将其编辑为包含“分组依据”之前阅读了您的解决方案。我想现在可以了。Thx。我认为这不正确。“select userId,max(time)”可能返回一个与表中主键不对应的值,即它可能给用户id 1,用户id为2的最大时间。@Scruffer,“主键”和“分组依据”在这里有什么关系??“时间”字段是否是主键的一部分并不重要。我想我在您将其编辑为包含“分组依据”之前阅读了您的解决方案。我想现在可以了。谢谢。