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,“主键”和“分组依据”在这里有什么关系??“时间”字段是否是主键的一部分并不重要。我想我在您将其编辑为包含“分组依据”之前阅读了您的解决方案。我想现在可以了。谢谢。