如何在oracle中以特定顺序选择数据

时间:2016-03-21 21:00:28

标签: sql oracle

我正在寻找一种在其他行上选择一行数据的方法。例如,如果我有以下数据:

FIRSTNAME    LASTNAME  STARTDATE    ENDDATE       FLG_DT
JIM          SMITH     01-MAR-1987  09-OCT-2001    BEFORE
JIM          SMITH     05-MAY-2003  07-DEC-2007    MATCH
JIM          SMITH     01-APR-2009  01-DEC-2015    AFTER
JIM          SMITH     01-APR-2016  01-APR-2016    NONE
JOHN         SMITH     01-MAY-2002  01-MAR-2016    MATCH
LORI         SMITH     20-JAN-2009  20-JAN-2010    BEFORE
LORI         SMITH     21-JAN-2010  01-MAR-2016    AFTER
ADAM         TAYLOR    01-APR-2016  01-APR-2016    NONE

基本上,对于不同的FIRSTNAME,LASTNAME,STARTDATE我想首先选择具有FLG_DT ='MATCH'的行。如果'MATCH'不存在,我想要选择FLG_DT ='BEFORE'的行,然后才开始。如果这些都不存在那么我想选择FLG_DT ='AFTER',如果那不存在那么我将采取'无。我可以在flg_dt字段中使用ROW_NUMBER()OVER PARTITION BY和ORDER BY,但不知道如何以此分层顺序选择它并将其他分开。结果应该是:

FIRSTNAME    LASTNAME  STARTDATE    ENDDATE       FLG_DT
JIM          SMITH     05-MAY-2003  07-DEC-2007    MATCH
JOHN         SMITH     01-MAY-2002  01-MAR-2016    MATCH
LORI         SMITH     20-JAN-2009  20-JAN-2010    BEFORE
ADAM         TAYLOR    01-APR-2016  01-APR-2016    NONE

感谢您的帮助。我觉得这对我来说应该是显而易见的,但我画了一个空白!

2 个答案:

答案 0 :(得分:4)

这是一种优先级。最简单的方法是使用row_number()

select t.*
from (select t.*,
             row_number() over (partition by firstname, lastname, startdate
                                order by (case when flg_dt = 'MATCH' then 1
                                               when flg_dt = 'BEFORE' then 2
                                               when flg_dt = 'AFTER' then 3
                                               else 4
                                          end)
                                ) as seqnum
      from t
     ) t
where seqnum = 1;

答案 1 :(得分:0)

您显示的数据表明您确实不希望它出现在DISTINCT FIRSTNAME,LASTNAME,STARTDATE上 - 您只需要不同的FIRSTNAME,LASTNAME。这是@ GordonLinoff查询的修改版本,它包含了这一变化:

select t.*
from (select your_table.*,
             row_number() over (partition by firstname, lastname
                                order by (case when flg_dt = 'MATCH' then 1
                                               when flg_dt = 'BEFORE' then 2
                                               when flg_dt = 'AFTER' then 3
                                               else 4
                                          end)
                                ) as seqnum
      from your_table
     ) t
where seqnum = 1;

并制作

FIRSTNAME   LASTNAME    STARTDATE           ENDDATE             FLG_DT  SEQNUM
ADAM        TAYLOR      April, 01 2016      April, 01 2016      NONE    1
JIM         SMITH       May, 05 2003        December, 07 2007   MATCH   1
JOHN        SMITH       May, 01 2002        March, 01 2016      MATCH   1
LORI        SMITH       January, 20 2009    January, 20 2010    BEFORE  1

SQLFiddle here

祝你好运。