我有一个表(Postgres 9.3)定义如下
CREATE TABLE tsrs (
id SERIAL PRIMARY KEY,
customer_id INTEGER NOT NULL REFERENCES customers,
timestamp TIMESTAMP WITHOUT TIME ZONE,
licensekeys_checksum VARCHAR(32));
此处的相关详细信息是customer_id,时间戳和licensekeys_checksum。此表中可以有多个具有相同customer_id的条目,其中一些可能具有匹配的licensekey_checksum条目,有些可能不同。
我有兴趣构建一个查询,该查询将为每组行返回一个包含1行的表,其中包含licensekeys_checksum条目。为每个组返回的行应该是具有最新/最新时间戳的条目。
我很抱歉,如果这很明显 - 我对SQL很新,而且我对这个查询有点不了解。任何帮助/指针将不胜感激!
示例输入
1, 2, 2014-08-21 16:03:35, 3FF2561A
2, 2, 2014-08-22 10:00:41, 3FF2561A
2, 2, 2014-06-10 10:00:41, 081AB3CA
3, 5, 2014-02-01 12:03:23, 299AFF90
4, 5, 2013-12-13 08:14:26, 299AFF90
5, 6, 2013-09-09 18:21:53, 49FFA891
期望的输出
2, 2, 2014-08-22 10:00:41, 3FF2561A
2, 2, 2014-06-10 10:00:41, 081AB3CA
3, 5, 2014-02-01 12:03:23, 299AFF90
5, 6, 2013-09-09 18:21:53, 49FFA891
编辑: 我已经设法根据以下评论拼凑查询,并在互联网上搜索数小时:)
select * from tsrs
inner join (
select licensekeys_checksum, max(timestamp) as mts
from tsrs
group by licensekeys_checksum )
x on x.licensekeys_checksum = tsrs.licensekeys_checksum and x.mts = tsrs.timestamp;
它似乎有效,但很难验证(如果我说我完全理解它是如何工作的话,我会说谎:))。如果我走在正确的轨道上,有人可以告诉我吗?
答案 0 :(得分:3)
您在问题中的查询应该比当前接受的答案中的查询执行得更好。使用EXPLAIN ANALYZE
进行测试。
如果您正在寻找更简单(也更快)的内容,请使用DISTINCT ON
:
SELECT DISTINCT ON (licensekeys_checksum) *
FROM tsrs
ORDER BY licensekeys_checksum, timestamp DESC;
SQL Fiddle - 建立在@WingedPanther(kudos)提供的基础之上 详细解释:
答案 1 :(得分:2)
试试这个
select *
from tsrs
where (timestamp,licensekeys_checksum) in (
select max(timestamp)
,licensekeys_checksum
from tsrs
group by licensekeys_checksum)
或
with cte as (
select id
,customer_id
,timestamp
,licensekeys_checksum
,row_number () over (partition by licensekeys_checksum ORDER BY timestamp DESC) as rk
from tsrs)
select id
,customer_id
,timestamp
,licensekeys_checksum
from cte where rk=1 order by id
答案 2 :(得分:2)
使用NOT EXISTS(...)
SELECT *
FROM tsrs t
WHERE NOT EXISTS (
SELECT *
FROM tsrs x
WHERE x.customer_id = t.customer_id -- same customer
AND x.licensekeys_checksum = t.licensekeys_checksum -- same checksum
AND x.ztimestamp > t.ztimestamp -- but more recent
);