我有一个包含以下列的数据库表:
id code value datetime timestamp
在此表中,唯一的唯一值位于id即主键。
我想根据日期时间值检索此表中最后一组不同的记录。例如,让我们说下面是我的表
id code value datetime timestamp
1 1023 23.56 2011-04-05 14:54:52 1234223421
2 1024 23.56 2011-04-05 14:55:52 1234223423
3 1025 23.56 2011-04-05 14:56:52 1234223424
4 1023 23.56 2011-04-05 14:57:52 1234223425
5 1025 23.56 2011-04-05 14:58:52 1234223426
6 1025 23.56 2011-04-05 14:59:52 1234223427
7 1024 23.56 2011-04-05 15:00:12 1234223428
8 1026 23.56 2011-04-05 15:01:14 1234223429
9 1025 23.56 2011-04-05 15:02:22 1234223430
我想检索ID为4,7,8和9的记录,即具有不同代码的最后一组记录(基于日期时间值)。我所强调的只是我想要实现的一个例子,因为这个表最终将包含数百万条记录和数百个单独的代码值。
我可以用什么SQL语句来实现这一目标?我似乎无法使用单个SQL语句完成它。我的数据库是MySQL 5.
答案 0 :(得分:65)
这应该适合你。
SELECT *
FROM [tableName]
WHERE id IN (SELECT MAX(id) FROM [tableName] GROUP BY code)
如果id是AUTO_INCREMENT,则无需担心计算成本高得多的日期时间,因为最近的日期时间也会具有最高的ID。
更新:从性能角度来看,确保在处理大量记录时将id
和code
列编入索引。如果id
是主键,则会内置,但您可能需要添加涵盖code
和id
的非聚集索引。
答案 1 :(得分:7)
试试这个:
SELECT *
FROM <YOUR_TABLE>
WHERE (code, datetime, timestamp) IN
(
SELECT code, MAX(datetime), MAX(timestamp)
FROM <YOUR_TABLE>
GROUP BY code
)
答案 2 :(得分:3)
这是老帖子,但用大表测试@smdrager的答案非常慢。我对此的解决方法是使用“内部联接”而不是“在哪里”。
SELECT *
FROM [tableName] as t1
INNER JOIN (SELECT MAX(id) as id FROM [tableName] GROUP BY code) as t2
ON t1.id = t2.id
这非常快。
答案 3 :(得分:1)
我会尝试这样的事情:
select * from table
where id in (
select id
from table
group by code
having datetime = max(datetime)
)
(免责声明:未经测试)
如果具有较大日期时间的行也具有更大的ID,则smdrager提出的解决方案更快。
答案 4 :(得分:0)
看起来所有现有答案都建议对整个表格进行GROUP BY code
处理。在逻辑上正确时,实际上此查询将遍历整张(!)表(使用EXPLAIN
进行确认)。就我而言,表中的行少于500k,执行...GROUP BY code
花费0.3秒,这是绝对不可接受的。
但是我可以在这里使用我的数据知识(读作“显示帖子的最新评论”):
code
的>>最高数量的记录中的数量通过试验数字,我发现,如果仅选择最后50条记录,总能找到20个不同的code
。在这种情况下,以下查询有效(记住@smdrager注释有关使用id
而不是datetime
的可能性很高)
SELECT id, code
FROM tablename
ORDER BY id DESC
LIMIT 50
仅选择最后50个条目非常快捷,因为它不需要检查整个表。剩下的就是从这50个条目中选择前20个具有不同的code
。
很明显,对50个(100,500)元素集的查询比对具有数十万个条目的整个表的查询要快得多。
原始SQL“后处理”
SELECT MAX(id) as id, code FROM
(SELECT id, code
FROM tablename
ORDER BY id DESC
LIMIT 50) AS nested
GROUP BY code
ORDER BY id DESC
LIMIT 20
这将为您提供id
的快速列表,如果您要执行其他JOIN,请将此查询作为另一个嵌套查询并对其执行所有联接。
后端“后处理”
然后,您需要使用编程语言处理数据,以仅将具有不同code
的记录包括到最终集中。
某种Python伪代码:
records = select_simple_top_records(50)
added_codes = []
top_records = []
for record in records:
# If record for this code was already found before
# Note: this is not optimal, better to use structure allowing O(1) search and insert
if record['code'] in added_codes:
continue
# Save record
top_records.append(record)
added_codes.append(record['code'])
# If we found all top-20 required, finish
if len(top_records) >= 20:
break