我有一个包含三列x, y, z
的表格。我想编写一个查询,在每个PARTITION BY x
内,返回包含n
的第一个y
个不同值的行。
这里是n = 2
的示例 - 第一个分区中y
的前2个不同值是1和2,第二个分区中有4和5,所以所有行都包含包含y
的值。
x y z included?
----------------------
1 1 1 true
1 1 2 true
1 2 3 true
1 2 4 true
1 3 5 false
1 3 6 false
2 4 7 true
2 4 8 true
2 5 9 true
2 5 10 true
2 6 11 false
2 6 12 false
有一个related question处理从每个分区中选择n
行,但这并不处理不同的值部分。
答案 0 :(得分:2)
我不确定你的意思"首先"。 SQL表表示无序集。所以,我假设你的意思是"最小的"。
您可以使用dense_rank()
:
select t.*
from (select t.*, dense_rank() over (partition by x order by y) as seqnum
from atable t
) t
where seqnum <= 2;
答案 1 :(得分:2)
您可以使用desnse_rank
和row_number
的组合来消除重复项:
with a as (
select
x, y, z,
dense_rank() over (partition by x order by y) rk,
row_number() over (partition by x, y order by z) rn
from
t
) select
x, y, z
from
a
where
rk <= 2 and
rn = 1;
这会生成1, 2, 4, 5
通过加入t:
,您可以获得所需的结果with a as (
select
x, y, z,
dense_rank() over (partition by x order by y) rk,
row_number() over (partition by x, y order by z) rn
from
t
) select
t.*
from
t
where
exists (
select
'x'
from
a
where
a.y = t.y and
a.rk <= 2 and
a.rn = 1
);
虽然以这种方式使用exists
会使重复项无关紧要,所以您可以这样做:
with a as (
select
x, y, z,
dense_rank() over (partition by x order by y) rk
from
t
) select
t.*
from
t
where
exists (
select
'x'
from
a
where
a.y = t.y and
a.rk <= 2
);