oracle如何按特定顺序选择数据

Posted

技术标签:

【中文标题】oracle如何按特定顺序选择数据【英文标题】:How to select data in a particular order in oracle 【发布时间】: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

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

【问题讨论】:

【参考方案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 ..这是一种罕见的情况,但偶尔会发生。 好的,好吧 - 祝你好运。

以上是关于oracle如何按特定顺序选择数据的主要内容,如果未能解决你的问题,请参考以下文章

按特定顺序选择特定行[重复]

Oracle group by子句按数据顺序排列

MySQL:按顺序插入选择

插入..按[重复]顺序选择

按特定表顺序选择三个表

列顺序很重要的 Oracle DB 简单 SELECT