简体   繁体   中英

Fetch next record within a table

I have the following table

EMP_ID     ,DATETIME_OF_MOVEMENT,CITY       ,RANK
2258325    ,1/18/2020 5:37      ,London     ,1
2258325    ,1/19/2020 11:01     ,Manchester ,2
2258325    ,1/20/2020 15:06     ,London     ,3
2656700    ,1/20/2020 23:59     ,London     ,1
2656700    ,1/21/2020 6:48      ,Manchester ,2
2656700    ,1/21/2020 6:48      ,Liverpool  ,3
2656700    ,1/26/2020 10:47     ,London     ,4
6631583    ,1/18/2020 18:00     ,London     ,1
6631583    ,1/19/2020 14:25     ,Manchester ,2
6631583    ,1/20/2020 8:53      ,Liverpool  ,3
6631583    ,1/20/2020 14:48     ,Manchester ,4
6631583    ,1/21/2020 11:34     ,London     ,5

I want a query to get the employee who were in london and come back to london. the firt location should be london second is the first location after london and third location should be london

I used the following query but it miss some employees

    select emp_id , date_of_movement as first_movement , city as first_city ,lead 
    (DATETIME_OF_MOVEMENT, 1) over ( partition by emp_id order by DATETIME_OF_MOVEMENT) as second_movement ,  
    lead (city , 1) over ( partition by emp_id order by DATETIME_OF_MOVEMENT) as second_city ,
    lead (DATETIME_OF_MOVEMENT, 2) over ( partition by emp_id order by DATETIME_OF_MOVEMENT) as third_movement ,  
    lead (city , 1) over ( partition by emp_id order by DATETIME_OF_MOVEMENT) as third_city ,
from table

result of the code

CUSTOMER_ID,first_movement ,first_city,second_movment ,second_movement,third_movment  ,third_city
2258325    ,1/18/2020 5:37 ,London    ,1/19/2020 11:01,Manchester     ,1/20/2020 15:06,London
2656700    ,1/20/2020 23:59,London    ,1/21/2020 6:48 ,Manchester     ,1/21/2020 6:48 ,Liverpool
6631583    ,1/18/2020 18:00,London    ,1/19/2020 14:25,Manchester     ,1/20/2020 8:53 ,Liverpool

This code catch the employee it their track of movement ( ex. emp_id : 2258325 ) 1 - London 2 - any other city 3 - London

It will not works fine If the movement of the employee like the following 1 - london 2 - any other city 3 - any other city 4 - London

i want the result to be like

CUSTOMER_ID,first_movement ,first_city,second_movement,second_city,third_movement ,third_city
2258325    ,1/18/2020 5:37 ,London    ,1/19/2020 11:01,Manchester ,1/20/2020 15:06,London
2656700    ,1/20/2020 23:59,London    ,1/21/2020 6:48 ,Manchester ,1/26/2020 10:47,London
6631583    ,1/18/2020 18:00,London    ,1/19/2020 14:25,Manchester ,1/21/2020 11:34,London

Any suggestion please?


 WITH YOUR_TABLE (EMP_ID,
                 DATETIME_OF_MOVEMENT,
                 CITY,
                 RANK_)
     AS (SELECT 2258325,
                '1/18/2020 5:37',
                'London',
                1
           FROM DUAL
         UNION ALL
         SELECT 2258325,
                '1/19/2020 11:01',
                'Manchester',
                2
           FROM DUAL
         UNION ALL
         SELECT 2258325,
                '1/20/2020 15:06',
                'London',
                3
           FROM DUAL
         UNION ALL
         SELECT 2656700,
                '1/20/2020 23:59',
                'London',
                1
           FROM DUAL
         UNION ALL
         SELECT 2656700,
                '1/21/2020 6:48',
                'Manchester',
                2
           FROM DUAL
         UNION ALL
         SELECT 2656700,
                '1/21/2020 6:48',
                'Liverpool',
                3
           FROM DUAL
         UNION ALL
         SELECT 2656700,
                '1/26/2020 10:47',
                'London',
                4
           FROM DUAL
         UNION ALL
         SELECT 6631583,
                '1/18/2020 18:00',
                'London',
                1
           FROM DUAL
         UNION ALL
         SELECT 6631583,
                '1/19/2020 14:25',
                'Manchester',
                2
           FROM DUAL
         UNION ALL
         SELECT 6631583,
                '1/20/2020 8:53',
                'Liverpool',
                3
           FROM DUAL
         UNION ALL
         SELECT 6631583,
                '1/20/2020 14:48',
                'Manchester',
                4
           FROM DUAL
         UNION ALL
         SELECT 6631583,
                '1/21/2020 11:34',
                'London',
                5
           FROM DUAL
           UNION ALL
         SELECT 6631583,
                '1/22/2020 14:48',
                'Manchester',
                6
           FROM DUAL
         UNION ALL
         SELECT 6631583,
                '1/24/2020 11:34',
                'London',
                7
           FROM DUAL)   -- YOUR QUERY STARTS FROM HERE   SELECT EMP_ID,
         MAX (CASE WHEN MINRN = RANK_ THEN DATETIME_OF_MOVEMENT END)
            AS first_movement,
         MAX (CASE WHEN MINRN = RANK_ THEN CITY END) AS first_CITY,
         MAX (CASE WHEN MINRN + 1 = RANK_ THEN DATETIME_OF_MOVEMENT END)
            AS SECOND_movement,
         MAX (CASE WHEN MINRN + 1 = RANK_ THEN CITY END) AS SECOND_CITY,
         MAX (CASE WHEN MAXRN = RANK_ THEN DATETIME_OF_MOVEMENT END)
            AS THIRD_movement,
         MAX (CASE WHEN MAXRN = RANK_ THEN CITY END) AS THIRD_CITY
    FROM (SELECT T.*,
                 MAX (CASE WHEN CITY = 'London' THEN RANK_ END)
                    OVER (PARTITION BY EMP_ID)
                    AS MAXRN,
                 MIN (CASE WHEN CITY = 'London' THEN RANK_ END)
                    OVER (PARTITION BY EMP_ID)
                    AS MINRN
            FROM YOUR_TABLE T)    WHERE MAXRN - MINRN > 1 GROUP BY EMP_ID;

check this it is not works @Tejash

result should be like this:

在此处输入图片说明

SELECT emp_id, 
       Lead (datetime_of_movement, 0) 
         OVER ( 
           partition BY emp_id 
           ORDER BY datetime_of_movement ASC)  AS first_movement, 
       Lead (city, 0) 
         OVER ( 
           partition BY emp_id 
           ORDER BY datetime_of_movement ASC)  AS first_city, 
       Lead (datetime_of_movement, 1) 
         OVER ( 
           partition BY emp_id 
           ORDER BY datetime_of_movement ASC) AS second_movement, 
       Lead (city, 1) 
         OVER ( 
           partition BY emp_id 
           ORDER BY datetime_of_movement ASC) AS second_city, 
       Lead (datetime_of_movement, 0) 
         OVER ( 
           partition BY emp_id 
           ORDER BY datetime_of_movement DESC) AS third_movement, 
       Lead (city, 0) 
         OVER ( 
           partition BY emp_id 
           ORDER BY datetime_of_movement DESC) AS third_city, 
FROM   table 
WHERE frist_city = "London" AND third_city = "London"

I couldn't test this SQL but maybe helpful. please let me know if it works for you.

You can try this below script. But this will return only onle row as only one EMP has city London where Rank = 3 ( and as per explanation your concern is location 3 as well)

DEMO HERE

SELECT 
DISTINCT A.EMP_ID CUSTOMER_ID,
A.DATETIME_OF_MOVEMENT first_movement ,A.city first_city,
B.DATETIME_OF_MOVEMENT secondt_movement,B.city second_city,
C.DATETIME_OF_MOVEMENT third_movement ,C.city third_city
FROM your_table A
INNER JOIN your_table B ON A.Rank = B.Rank - 1 AND A.EMP_ID = B.EMP_ID
INNER JOIN your_table C ON A.Rank = C.Rank - 2 AND A.EMP_ID = C.EMP_ID
WHERE A.RANK = 1
AND C.City = 'London'

New logic if the last city is not the third city-

DEMO HERE

WITH CTE AS
(
    SELECT A.EMP_ID,A.DATETIME_OF_MOVEMENT,A.CITY,A.RANK, 
    CASE WHEN A.RANK > 2 THEN 3 ELSE A.Rank END NEW_RANK 
    FROM your_table A
    WHERE A.RANK IN (1,2)
    OR A.RANK = (SELECT MAX(Rank) FROM your_table B WHERE B.EMP_ID = A.EMP_ID)
)

SELECT 
A.EMP_ID CUSTOMER_ID,
A.DATETIME_OF_MOVEMENT first_movement ,A.city first_city,
B.DATETIME_OF_MOVEMENT secondt_movement,B.city second_city,
C.DATETIME_OF_MOVEMENT third_movement ,C.city third_city
FROM CTE A
INNER JOIN CTE B ON A.NEW_RANK = B.NEW_RANK - 1 AND A.EMP_ID = B.EMP_ID
INNER JOIN CTE C ON A.NEW_RANK = C.NEW_RANK - 2 AND A.EMP_ID = C.EMP_ID
WHERE A.NEW_RANK = 1
AND C.City = 'London'

I think you need a record starting from London then next record and the last London record. You can use the combination of the conditional aggregate and analytical function as following:

 SQL> WITH YOUR_TABLE ( 2 EMP_ID, 3 DATETIME_OF_MOVEMENT, 4 CITY, 5 RANK 6 ) AS 7 ( 8 SELECT 2258325 ,'1/18/2020 5:37' ,'London' ,1 FROM DUAL UNION ALL 9 SELECT 2258325 ,'1/19/2020 11:01' ,'Manchester' ,2 FROM DUAL UNION ALL 10 SELECT 2258325 ,'1/20/2020 15:06' ,'London' ,3 FROM DUAL UNION ALL 11 SELECT 2656700 ,'1/20/2020 23:59' ,'London' ,1 FROM DUAL UNION ALL 12 SELECT 2656700 ,'1/21/2020 6:48' ,'Manchester' ,2 FROM DUAL UNION ALL 13 SELECT 2656700 ,'1/21/2020 6:48' ,'Liverpool' ,3 FROM DUAL UNION ALL 14 SELECT 2656700 ,'1/26/2020 10:47' ,'London' ,4 FROM DUAL UNION ALL 15 SELECT 6631583 ,'1/18/2020 18:00' ,'London' ,1 FROM DUAL UNION ALL 16 SELECT 6631583 ,'1/19/2020 14:25' ,'Manchester' ,2 FROM DUAL UNION ALL 17 SELECT 6631583 ,'1/20/2020 8:53' ,'Liverpool' ,3 FROM DUAL UNION ALL 18 SELECT 6631583 ,'1/20/2020 14:48' ,'Manchester' ,4 FROM DUAL UNION ALL 19 SELECT 6631583 ,'1/21/2020 11:34' ,'London' ,5 FROM DUAL 20 ) 21 -- YOUR QUERY STARTS FROM HERE 22 SELECT 23 EMP_ID, 24 MAX(CASE WHEN MINRN = RANK THEN DATETIME_OF_MOVEMENT END) AS first_movement, 25 MAX(CASE WHEN MINRN = RANK THEN CITY END) AS first_CITY, 26 MAX(CASE WHEN MINRN + 1 = RANK THEN DATETIME_OF_MOVEMENT END) AS SECOND_movement, 27 MAX(CASE WHEN MINRN + 1 = RANK THEN CITY END) AS SECOND_CITY, 28 MAX(CASE WHEN MAXRN = RANK THEN DATETIME_OF_MOVEMENT END) AS THIRD_movement, 29 MAX(CASE WHEN MAXRN = RANK THEN CITY END) AS THIRD_CITY 30 FROM 31 ( 32 SELECT T.*, 33 MAX(CASE WHEN CITY = 'London' THEN RANK END) OVER(PARTITION BY EMP_ID) AS MAXRN, 34 MIN(CASE WHEN CITY = 'London' THEN RANK END) OVER(PARTITION BY EMP_ID) AS MINRN 35 FROM YOUR_TABLE T 36 ) 37 WHERE MAXRN - MINRN > 1 38 GROUP BY EMP_ID; EMP_ID FIRST_MOVEMENT FIRST_CITY SECOND_MOVEMENT SECOND_CIT THIRD_MOVEMENT THIRD_CITY ---------- --------------- ---------- --------------- ---------- --------------- ---------- 2258325 1/18/2020 5:37 London 1/19/2020 11:01 Manchester 1/20/2020 15:06 London 2656700 1/20/2020 23:59 London 1/21/2020 6:48 Manchester 1/26/2020 10:47 London 6631583 1/18/2020 18:00 London 1/19/2020 14:25 Manchester 1/21/2020 11:34 London SQL>

Cheers!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM