Question

I wanted to retrieve records from a table by comparing with previous entry (for that account). Please take a look the table and data below.

In this out put I wanted is,

ID_NUM  DELIVERY_TYPE
100     2                
101     2
102     2

Explanation: I need, 100 because it is its first occurance with DELIVERY_TYPE IS 2 (Old record has 1) 101 because it is its first occurance with DELIVERY_TYPE IS 2 (Old record has 3) 102 because there is only one entry for this ID_NUM and DELIVERY_TYPE IS 2

I DON'T NEED 103 because recent DELIVERY_TYPE IS 1 even it has DELIVERY_TYPE IS 2 104 because it has two or more records with DELIVERY_TYPE IS 2

Any body knows how to achieve this result?

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'));
Was it helpful?

Solution

You can use the ROW_NUMBER() function to isolate the most recent rows by partitioning on the ID_NUM and ordering by the CREATED_DATE descending. Then identify the occurrences of more than one DELIVERY_TYPE = 2 to filter the result set:

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)

This will return the expected results.

OTHER TIPS

use a LAG function.

it might be easier if you post a small table of values for your example instead of (/in addition to) your insert statements.

This query will give you your desired output for the given input though I don't fully understand your rules:

  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  

If you expand on what happens if, say, an ID_NUM has only one entry but it is not of DELIVERY_TYPE = 1 for example then perhaps I can update.

The following query returns one record for each id_num where the last delivery_type was 2 and the value 2 appeared in delivery_type exactly once:

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top