SQL查询从多个等级/组中选择第一个等级1行 [英] SQL Query Select first rank 1 row From Multiple ranks/Group

查看:174
本文介绍了SQL查询从多个等级/组中选择第一个等级1行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下数据

表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.您不会谈论要如何处理联系,甚至是否可能联系,因此从问题本身还不清楚您是否要使用rankdense_rankrow_number分析函数.如果仅按id获取最高排名的行,则rankdense_rank的行为将相同,并且如果有联系,则将返回多行. row_number将始终通过任意打破平局来返回单行.如果要获取每个id的第一行以外的行,则需要考虑联系,您将获得与rankdense_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆