【问题标题】:Union resulting in duplicate rows - Oracle SQL联合导致重复行 - Oracle SQL
【发布时间】:2019-09-03 05:55:27
【问题描述】:

我有一个如下所示的数据集:

|  Order | Step | Step_Complete_Date |
|:------:|:----:|:------------------:|
| ABC454 |   1  |     12/21/2018     |
| ABC454 |   2  |     12/22/2018     |
| ABC454 |   3  |        NULL        |
| ABC454 |   4  |     12/23/2018     |
| ABC454 |   5  |     12/23/2018     |
| ABC433 |   1  |      1/1/2019      |
| ABC433 |   2  |      1/1/2019      |
| ABC433 |   3  |      1/2/2019      |
| ABC433 |   4  |      1/3/2019      |
| ABC433 |   5  |      1/7/2019      |
| ABC600 |   1  |      2/1/2019      |
| ABC600 |   2  |      2/7/2019      |
| ABC600 |   3  |      3/1/2019      |
| ABC600 |   4  |        NULL        |
| ABC600 |   5  |        NULL        |
| ABC800 |   1  |      5/1/2019      |
| ABC800 |   2  |      5/5/2019      |
| ABC800 |   3  |      5/5/2019      |
| ABC800 |   4  |      5/5/2019      |
| ABC800 |   5  |        NULL        |
| ABC999 |   1  |      7/1/2019      |
| ABC999 |   2  |      7/1/2019      |
| ABC999 |   3  |      7/1/2019      |
| ABC999 |   4  |      7/1/2019      |
| ABC999 |   5  |        NULL        |

我需要编写 SQL 查询来查找已完成第 4 步或第 5 步的任何订单(即Step_Completed_Date 不为空)

我尝试了以下方法:

WITH
  step4 AS
    (
       SELECT Order_No, Step_No, Step_Complete_Date AS Step_4_Complete_Date, NULL AS Step_5_Complete_Date
       FROM tblSteps
       WHERE Step_No = '4' AND Step_Complete_Date IS NOT NULL
     ),

   step5 AS
    (
       SELECT Order_No, Step_No, NULL AS Step_4_Complete_Date, Step_Complete_Date AS Step_5_Complete_Date
       FROM tblSteps
       WHERE Step_No = '5' AND Step_Complete_Date IS NOT NULL
     )

   SELECT * FROM Step4
   UNION
   SELECT * FROM Step5

但它会导致:

| ORDER_NO | STEP_NO | STEP_4_COMPLETE_DATE | STEP_5_COMPLETE_DATE |
|:--------:|:-------:|:--------------------:|:--------------------:|
|  ABC433  |    4    |       1/3/2019       |        (null)        |
|  ABC433  |    5    |        (null)        |       1/7/2019       |
|  ABC454  |    4    |      12/23/2018      |        (null)        |
|  ABC454  |    5    |        (null)        |      12/23/2018      |
|  ABC800  |    4    |       5/5/2019       |        (null)        |
|  ABC999  |    4    |       7/1/2019       |        (null)        |

理想情况下,它看起来像:

| ORDER_NO | STEP_4_COMPLETE_DATE | STEP_5_COMPLETE_DATE |
|:--------:|:--------------------:|:--------------------:|
|  ABC433  |       1/3/2019       |       1/7/2019       |
|  ABC454  |      12/23/2018      |      12/23/2018      |
|  ABC800  |       5/5/2019       |        (null)        |
|  ABC999  |       7/1/2019       |        (null)        |

如何更改我的 SQL 以创建所需的输出?我已经设置了SQL FIDDLE here

【问题讨论】:

    标签: sql oracle oracle11g union


    【解决方案1】:

    我会在这里聚合,然后使用HAVING 子句来断言哪些订单匹配,哪些不匹配:

    SELECT
        ORDER_NO,
        MAX(CASE WHEN Step = 4 THEN Step_Complete_Date END) AS STEP_4_COMPLETE_DATE,
        MAX(CASE WHEN Step = 5 THEN Step_Complete_Date END) AS STEP_5_COMPLETE_DATE
    FROM tblSteps
    GROUP BY
        ORDER_NO
    HAVING
        COUNT(CASE WHEN Step IN (4, 5) AND Step_Complete_Date IS NOT NULL THEN 1 END) > 0;
    

    【讨论】:

      【解决方案2】:

      您可以在下面尝试 - 使用聚合和分组方式

      WITH
        step4 AS
          (
             SELECT Order_No, Step_No, Step_Complete_Date AS Step_4_Complete_Date, NULL AS Step_5_Complete_Date
             FROM tblSteps
             WHERE Step_No = '4' AND Step_Complete_Date IS NOT NULL
           ),
      
         step5 AS
          (
             SELECT Order_No, Step_No, NULL AS Step_4_Complete_Date, Step_Complete_Date AS Step_5_Complete_Date
             FROM tblSteps
             WHERE Step_No = '5' AND Step_Complete_Date IS NOT NULL
           )
      
         SELECT SELECT Order_No, ,max(Step_4_Complete_Date),max(Step_5_Complete_Date) FROM Step4 group by Order_No, 
         UNION
         SELECT SELECT Order_No ,max(Step_4_Complete_Date),max(Step_5_Complete_Date) FROM Step5 group by Order_No
      

      【讨论】:

        【解决方案3】:

        你可以试试GROUP BY如下:

        SELECT Order_No, '4' AS Step_No, 
        MAX(CASE WHEN Step_No = 4 THEN Step_Complete_Date END) AS Step_4_Complete_Date, 
        MAX(CASE WHEN Step_No = 5 THEN Step_Complete_Date END) AS Step_4_Complete_Date
        FROM tblSteps
        WHERE Step_No IN ('4','5') AND Step_Complete_Date IS NOT NULL
        GROUP BY Order_No
        

        SQL Fiddle demo

        干杯!!

        【讨论】:

          【解决方案4】:

          条件聚合的一个版本

          SELECT
              ORDER_NO,
              MAX(CASE WHEN Step = 4 THEN Step_Complete_Date END) AS STEP_4_COMPLETE_DATE,
              MAX(CASE WHEN Step = 5 THEN Step_Complete_Date END) AS STEP_5_COMPLETE_DATE
          FROM tblSteps
          WHERE Step IN (4, 5)
          GROUP BY ORDER_NO
          HAVING COUNT(Step_Complete_Date) > 0;
          

          【讨论】:

            【解决方案5】:

            您可以使用数据透视函数将步骤 4 完成日期和步骤 5 完成日期作为列

            select * from
            (
            select order_no , step_complete_date , step_no from tblSteps where step_no in (4,5)
            )
            pivot
            (
              max(step_complete_date)
              for step_no in ( 4 as step_4_complete_dt , 5 as step_5_complete_dt)
            )
            where    nvl (step_4_complete_dt ,step_5_complete_dt ) is not null 
            

            最后一个 where 子句是去掉 4 和 5 的完成日期都为空的行

            注意,step_no 列不会出现在这里,我不清楚为什么你需要 step no 列,如果它在一行中显示两个步骤的完成日期

            希望这能解决你的目的

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-01-27
              • 2010-12-28
              • 1970-01-01
              • 2020-08-03
              • 2018-09-20
              • 2017-02-18
              相关资源
              最近更新 更多