【问题标题】:SQL: Compare row with previous row based on a specific conditionSQL:根据特定条件将行与上一行进行比较
【发布时间】:2012-02-14 23:10:33
【问题描述】:

我想通过与以前的条目(针对该帐户)进行比较来从表中检索记录。 请看下表和数据。

在这个输出中我想要的是,

ID_NUM  DELIVERY_TYPE
100     2                
101     2
102     2

解释:我需要, 100,因为它是第一次出现 DELIVERY_TYPE IS 2(旧记录有 1) 101,因为它是第一次出现 DELIVERY_TYPE IS 2(旧记录有 3) 102 因为这个 ID_NUM 只有一个条目,并且 DELIVERY_TYPE 是 2

我不需要 103 因为最近的 DELIVERY_TYPE IS 1 即使它有 DELIVERY_TYPE IS 2 104,因为它有两条或更多条 DELIVERY_TYPE 为 2 的记录

任何机构都知道如何达到这个结果?

CREATE TABLE DEMO
  (
    ID_NUM         NUMBER(10,0),
    DELIVERY_TYPE  NUMBER(2,0),
    NAME           VARCHAR2(100),
    CREATED_DATE   DATE
  );


INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (100, 2, TO_DATE('10-FEB-12 11:08:49 AM', 'DD-MON-RR HH:MI:SS AM'));
INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (100, 1, TO_DATE('29-JAN-12 11:09:00 AM', 'DD-MON-RR HH:MI:SS AM'));

INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (101, 2, TO_DATE('09-FEB-12 11:09:26 AM', 'DD-MON-RR HH:MI:SS AM'));
INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (101, 3, TO_DATE('14-JAN-12 11:09:33 AM', 'DD-MON-RR HH:MI:SS AM'));

INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (102, 2, TO_DATE('02-FEB-12 10:09:26 AM', 'DD-MON-RR HH:MI:SS AM'));

INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (103, 1, TO_DATE('01-FEB-12 10:09:26 AM', 'DD-MON-RR HH:MI:SS AM'));
INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (103, 2, TO_DATE('02-JAN-12 11:09:33 AM', 'DD-MON-RR HH:MI:SS AM'));

INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (104, 2, TO_DATE('02-FEB-12 10:09:26 AM', 'DD-MON-RR HH:MI:SS AM'));
INSERT INTO DEMO
  (ID_NUM, DELIVERY_TYPE, CREATED_DATE)
VALUES
  (104, 2, TO_DATE('02-FEB-12 10:09:26 AM', 'DD-MON-RR HH:MI:SS AM'));

【问题讨论】:

  • 所以规则不是你得到每个 id_num 的最后一个交付类型。你能解释一下不返回 id_num 103 和 104 背后的逻辑吗?

标签: sql oracle compare multiple-records


【解决方案1】:

使用 LAG 函数。

如果您为示例发布一个小值表而不是(/除了)您的插入语句,这可能会更容易。

【讨论】:

    【解决方案2】:

    您可以使用 ROW_NUMBER() 函数通过按 ID_NUM 分区并按 CREATED_DATE 降序排序来隔离最近的行。然后识别多个DELIVERY_TYPE = 2的出现来过滤结果集:

    SELECT ID_NUM, DELIVERY_TYPE
    FROM (SELECT ID_NUM, DELIVERY_TYPE,
                 ROW_NUMBER() OVER (PARTITION BY ID_NUM
                                    ORDER BY CREATED_DATE DESC) AS RN
          FROM DEMO)
    WHERE RN = 1
    AND DELIVERY_TYPE = 2
    MINUS
    SELECT ID_NUM, DELIVERY_TYPE
    FROM (SELECT ID_NUM, DELIVERY_TYPE, COUNT(*) AS REC_COUNT
          FROM DEMO
          WHERE DELIVERY_TYPE = 2
          GROUP BY ID_NUM, DELIVERY_TYPE
          HAVING COUNT(*) > 1)
    

    这将返回预期的结果。

    【讨论】:

      【解决方案3】:

      尽管我不完全理解您的规则,但此查询将为您提供给定输入所需的输出:

        select ID_NUM, DELIVERY_TYPE
          from (  select ID_NUM, DELIVERY_TYPE, CREATED_DATE
                    from DEMO
                group by ID_NUM, DELIVERY_TYPE, CREATED_DATE
                  having count(*) = 1) CNT1
         where CREATED_DATE = (select max(CREATED_DATE)
                                 from DEMO D
                                where D.ID_NUM = CNT1.ID_NUM)
               and DELIVERY_TYPE <> 1
      order by ID_NUM, DELIVERY_TYPE, CREATED_DATE  
      

      如果您扩展如果 ID_NUM 只有一个条目但它不是 DELIVERY_TYPE = 1 时会发生什么,那么也许我可以更新。

      【讨论】:

        【解决方案4】:

        以下查询为每个 id_num 返回一条记录,其中最后一个 delivery_type 为 2,而值 2 在 delivery_type 中只出现一次:

        SELECT DISTINCT id_num, last_delivery_type
        FROM   (SELECT id_num,
                       FIRST_VALUE(delivery_type) 
                          OVER (PARTITION BY id_num 
                                ORDER BY created_date DESC) 
                          AS last_delivery_type,
                       COUNT(CASE WHEN delivery_type = 2 
                                  THEN 2 ELSE NULL END) 
                          OVER (PARTITION BY id_num) AS delivery_type_2_cnt
                FROM   demo)
        WHERE  last_delivery_type = 2 AND delivery_type_2_cnt = 1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-14
          • 1970-01-01
          • 1970-01-01
          • 2022-10-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多