[英]SQL group by: select value where another column has its min/max
我想按一列分組,同時獲取第二列的最小值和最大值,並且(這是棘手的部分。)從第三列獲取值,其中第二列在組中具有其最小值。
例子:
我的表:
ID TS GRP
==================
1 20 A
2 20 B
3 10 A
4 30 A
5 10 B
6 40 A
期望的結果(ID 應該是 TS 最小值的記錄中的值):
ID MIN_TS MAX_TS GRP
============================
3 10 40 A
5 10 20 B
一般來說,分組查詢很容易:
SELECT <???> AS ID, MIN(TS) AS MIN_TS, MAX(TS) AS MAX_TS, GRP
FROM MyTable
GROUP BY GRP
但是 ID 部分呢? 它不適用於分組,對嗎? 但為什么? 最好的解決方法是什么?
在子查詢中進行匯總,然后在另一個子查詢中查找每個組的ID:
SELECT
(SELECT TOP(1) id FROM MyTable WHERE grp = agg.grp ORDER BY ts DESC) AS id,
min_ts, max_ts, grp
FROM (SELECT min(ts) AS min_ts, max(ts) AS max_ts, grp
FROM MyTable
GROUP BY grp) agg
或使用窗口功能:
SELECT id, min_ts, max_ts, grp
FROM (SELECT
id,
min(ts) OVER (PARTITION BY grp) min_ts,
max(ts) OVER (PARTITION BY grp) max_ts,
grp,
row_number OVER (PARTITION BY grp ORDER BY ts) rn
FROM MyTable)
WHERE rn = 1;
該查詢使用窗口函數來計算每個組的min_ts
和max_ts
,然后過濾以僅包括每個組的第一行(按ts
排序)。
有點晚了,但對於未來的人......
我可以提出另一種解決方案,它與現有的有點不同,它的想法基本相同,但它以另一種方式實現(而且它可能更快一點?)。
所以你基本上可以在子查詢中進行所有分組和聚合(使用WITH
),然后在該查詢和你的原始表之間使用INNER JOIN
來獲得你想要的東西,它會是這樣的......
WITH values AS (
SELECT
MIN(ts) as min_ts,
MAX(ts) AS max_ts,
grp
FROM MyTable
GROUP BY grp
)
SELECT
tb.id AS id,
v.min_ts AS min_ts,
v.max_ts AS max_ts,
tb.grp AS grp
FROM MyTable tb
INNER JOIN values v ON v.grp = tb.grp AND v.min_ts = tb.ts;
這有點簡單,也更直觀(至少對我而言)。
我已經在 Postgres DB 上對此進行了測試,並針對以下數據
id | ts | grp
----+----+-----
7 | 5 | A
3 | 10 | A
1 | 20 | A
5 | 30 | A
4 | 10 | B
2 | 20 | B
6 | 30 | B
8 | 60 | B
它給出了以下結果
id | min_ts | max_ts | grp
----+--------+--------+-----
7 | 5 | 30 | A
4 | 10 | 60 | B
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.