[英]How to select up to x rows when records have to be grouped based on criteria
我想創建查詢,我最多選擇 x 行,記錄按一個 id 分組,並且整個組必須是查詢的結果。 我基於過濾的值存儲在 p_id 列中,具有相同值的行創建組。 在該表的情況下:
p_id age
0 00170 64
1 00170 64
2 00201 24
3 00201 64
4 00201 64
5 00300 24
6 00300 20
我想選擇 4 行,但是因為 p_id 為 00170,00201 的組總共有 5 條記錄,所以我得到了:
0 00170 64
1 00170 64
如果我選擇 5 行,我會得到:
0 00170 64
1 00170 64
2 00201 24
3 00201 64
4 00201 64
如果我要選擇 6 行,我會得到(p_id 00300 是 2 條記錄,因此不包括在內,因為總和超過 6):
0 00170 64
1 00170 64
2 00201 24
3 00201 64
4 00201 64
所以整個組都返回了。 我正在使用 oracle db,使用 ROWNUM 可以輕松選擇 x 行。 當我嘗試使用附加條件達到一定數量的行時,我迷路了。
甲骨文設置:
CREATE TABLE test_data ( p_id, age ) AS
SELECT '00170', 64 FROM DUAL UNION ALL
SELECT '00170', 64 FROM DUAL UNION ALL
SELECT '00201', 24 FROM DUAL UNION ALL
SELECT '00201', 64 FROM DUAL UNION ALL
SELECT '00201', 64 FROM DUAL UNION ALL
SELECT '00300', 24 FROM DUAL UNION ALL
SELECT '00300', 20 FROM DUAL;
查詢:
對行進行排序,然后找到每個組的最大行號,然后過濾以僅返回最大行號包含在所需行限制中的組:
SELECT p_id,
age
FROM (
SELECT t.*,
MAX( ROWNUM ) OVER ( PARTITION BY p_id ) AS grp
FROM (
SELECT *
FROM test_data
ORDER BY p_id
) t
)
WHERE grp <= 4;
輸出:
\n P_ID | 年齡\n :---- | ——:\n 00170 | 64\n 00170 | 64\n
如果您將最后一行更改為 5,則它將返回 5 行並將其更改為 6,則它仍將返回 5 行。
db<> 在這里擺弄
我會用窗口計數和過濾來解決這個問題:
select p_id, age
from (select p_id, age, count(*) over(order by p_id) cnt from mytable t) t
where cnt <= 5
order by p_id
您可以根據需要更改cnt <= 5
。
cnt <= 4
:
P_ID | AGE ---: | --: 170 | 64 170 | 64
cnt <= 5
:
P_ID | AGE ---: | --: 170 | 64 170 | 64 201 | 24 201 | 64 201 | 64
cnt <= 6
:
P_ID | AGE ---: | --: 170 | 64 170 | 64 201 | 24 201 | 64 201 | 64
GMB 的回答很好。 但是可以通過使用RANK()
來簡化它。 此功能恰好做的正是你想要的東西:
select p_id, age
from (select t.*,
rank() over (order by p_id) as rnk
from t
) t
where rnk <= 5
order by p_id;
更重要的是,如果p_id
值沒有排序,那么您可能需要一個額外的步驟:將某個排序列的最小值分配給每個p_id
。 讓我稱之為排序列id
:
select p_id, age
from (select t.*,
rank() over (order by p_id_grp) as rnk
from (select t.*, min(id) over (partition by p_id) as p_id_grp
from t
) t
) t
where rnk <= 5
order by p_id;
這是一個典型的 Top-N 查詢:
將 ROWNUM 與有序視圖一起使用以獲得正確的排序:
SELECT p_id, age
FROM (SELECT p_id, age
FROM table
ORDER BY age DESC)
WHERE ROWNUM <= 4;
對於 Oracle v 12c 以后的版本,有新的 FETCH 子句:
SELECT p_id, age
FROM table
GROUP BY p_id
FETCH FIRST 4 ROWS ONLY;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.