SQL:根据特定条件将行与上一行进行比较

时间:2012-02-14 23:10:33

标签: sql oracle compare multiple-records

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

在我想要的输出中,

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 IS 2只有一个条目

我不需要 103因为最近的DELIVERY_TYPE是1,即使它有DELIVERY_TYPE IS 2 104因为它有两个或多个带有DELIVERY_TYPE IS 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'));

4 个答案:

答案 0 :(得分:2)

使用LAG功能。

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

答案 1 :(得分:1)

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

  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,那么也许我可以更新。

答案 2 :(得分:1)

您可以使用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 :(得分:1)

以下查询为每个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