【问题标题】:How to select data in a particular order in oracleoracle如何按特定顺序选择数据
【发布时间】:2016-03-21 21:00:28
【问题描述】:

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

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',如果不存在,那么我将选择'NONE。我可以在 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

感谢您的帮助。我觉得这对我来说应该很明显,但我画的是空白!

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    这是一种优先级。最简单的方法是使用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;
    

    【讨论】:

    • 谢谢..这很好用。我很惊讶地看到它是如何工作的,因为无论如何,seqnum 最终都是 1,所以'THEN' 并没有真正分配值。它只是像你提到的那样对它进行排序/优先级,这使得 WHERE seqnum = 1 工作。这根本不是我认为有效的方式,但现在我明白了。
    【解决方案2】:

    您显示的数据表明您真的不希望它在 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

    祝你好运。

    【讨论】:

    • 感谢您的回复。我确实希望上述不同的 STARTDATE ..这是一种罕见的情况,但偶尔会发生。
    • 好的,好吧 - 祝你好运。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 2014-01-07
    • 2019-10-31
    • 2021-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多