SQL查询从多个等级/组中选择第一个等级1行 [英] SQL Query Select first rank 1 row From Multiple ranks/Group
问题描述
我有以下数据
表1
id col1 col2 col3
----------------------------------
1 abc 01/01/2012 -
1 abc 01/01/2012 A
2 abc 01/01/2012 -
2 abc 01/02/2012 -
3 abc 01/02/2012 -
3 xyz 01/01/2012 -
4 abc 01/02/2012 -
4 xyz 01/01/2012 -
4 xyz 01/02/2012 -
以下是评估的顺序-
if(col1 is false) then evaluate col2 if(col2 is false) then col3:
Col1 - xyz has first preference from all values in this column
col2 - min date
col3 - not '-' or min(col3)
我只想为每个id返回一行,如果col1失败,请转到col2,如果失败,则转到col3条件. 从上表得出的结果应该是
I want to return only one row for each id, if col1 fails go to col2, if this fails then go to col3 condition. From above table result should be
id col1 col2 col3
----------------------------------
1 abc 01/01/2012 A
2 abc 01/01/2012 -
3 xyz 01/01/2012 -
4 xyz 01/01/2012 -
我尝试使用密集等级,但没有帮助.我不确定如何使用任何可用的函数或sql逻辑执行此逻辑.
I tried using dense rank but it didn't help. I'm not sure how to perform this logic using any available function or sql logic.
for col1 - if more than one row for same code or xyz code then fail
for col2 - if more than one row with same min date then fail
[use this only if col1 condition fails]
推荐答案
您可以在解析函数中指定许多要排序的条件
You can specify many conditions to order by in your analytic function
SELECT *
FROM (SELECT id,
col1,
col2,
col3,
dense_rank() over (partition by id
order by (case when col1 = 'xyz'
then 1
else 0
end) desc,
col2 asc,
col3 asc) rnk
FROM your_table)
WHERE rnk = 1
考虑到您使用了dense_rank
标记,我假设您想要dense_rank
.您不会谈论要如何处理联系,甚至是否可能联系,因此从问题本身还不清楚您是否要使用rank
,dense_rank
或row_number
分析函数.如果仅按id
获取最高排名的行,则rank
和dense_rank
的行为将相同,并且如果有联系,则将返回多行. row_number
将始终通过任意打破平局来返回单行.如果要获取每个id
的第一行以外的行,则需要考虑联系,您将获得与rank
和dense_rank
不同的行为.如果将两行并列放置,则dense_rank
将为第三行分配rnk
为2,而rank
将为其分配rnk
为3.
I'm assuming that you want dense_rank
given that you used the dense_rank
tag. You don't talk about how you want to handle ties or whether ties are even possible, so it's not clear from the question itself whether you want to use the rank
, dense_rank
, or row_number
analytic functions. If you are only ever fetching the highest ranking row per id
, rank
and dense_rank
will behave identically and will return multiple rows if there are ties for first place. row_number
will always return a single row by arbitrarily breaking the tie. If you want to fetch rows other than the first row per id
, then you'll need to think about ties and you'll get different behavior from rank
and dense_rank
. If two rows are tied for first, dense_rank
will assign the third row a rnk
of 2 while rank
will assign it a rnk
of 3.
这似乎适用于您发布的示例数据
This seems to work for the sample data you posted
SQL> ed
Wrote file afiedt.buf
1 with x as (
2 select 1 id, 'abc' col1, to_date('01/01/2012', 'MM/DD/YYYY') col2, null col3 from dual union all
3 select 1 id, 'abc' col1, to_date('01/01/2012', 'MM/DD/YYYY') col2, 'A' col3 from dual union all
4 select 2 id, 'abc' col1, to_date('01/01/2012', 'MM/DD/YYYY') col2, null col3 from dual union all
5 select 2 id, 'abc' col1, to_date('01/02/2012', 'MM/DD/YYYY') col2, null col3 from dual union all
6 select 3 id, 'abc' col1, to_date('01/02/2012', 'MM/DD/YYYY') col2, null col3 from dual union all
7 select 3 id, 'xyz' col1, to_date('01/01/2012', 'MM/DD/YYYY') col2, null col3 from dual union all
8 select 4 id, 'abc' col1, to_date('01/02/2012', 'MM/DD/YYYY') col2, null col3 from dual union all
9 select 4 id, 'xyz' col1, to_date('01/01/2012', 'MM/DD/YYYY') col2, null col3 from dual union all
10 select 4 id, 'xyz' col1, to_date('01/02/2012', 'MM/DD/YYYY') col2, null col3 from dual
11 )
12 SELECT *
13 FROM (SELECT id,
14 col1,
15 col2,
16 col3,
17 dense_rank() over (partition by id
18 order by (case when col1 = 'xyz'
19 then 1
20 else 0
21 end) desc,
22 col2 asc,
23 col3 asc) rnk
24 FROM x)
25* WHERE rnk = 1
SQL> /
ID COL COL2 C RNK
---------- --- --------- - ----------
1 abc 01-JAN-12 A 1
2 abc 01-JAN-12 1
3 xyz 01-JAN-12 1
4 xyz 01-JAN-12 1
这篇关于SQL查询从多个等级/组中选择第一个等级1行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!