简体   繁体   中英

fetch next and scan records within the same table

I have the following table

在此处输入图片说明

data is accessible here

https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=18e9473c82deb4e7e955a0b0cb6f5014

I want to find the employee if he has a city = 'London' and next row after that <> 'London'. After that I should scan the rest rows and catch first row = 'London', if not i should ignore the entire row. the result should be like below

在此处输入图片说明

My code and result:

在此处输入图片说明

https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=cc7863dbe59f80d1058f34a8f7ad0562

Code works if

first city = London
Second city != London
third city = London

But if London instead of coming as a third city let say fourth or fifth it will not works. Code should be:

first city = London 
Second city <> London
third city = London if not check next
fourth city = London if not check next
...
to last row for the employee if not find London, skip the entire row.

**

I think LEAD() with some CASE logic and IGNORE NULL s does what you want:

SELECT * 
FROM (SELECT t.*,
             LEAD(CITY) OVER (PARTITION BY EMP_ID ORDER BY DATETIME) as city_2,
             LEAD(datetime) OVER (PARTITION BY EMP_ID ORDER BY DATETIME) as datetime_2,
             LEAD(CASE WHEN CITY = 'London' THEN CITY END IGNORE NULLS) OVER (PARTITION BY EMP_ID ORDER BY DATETIME) as city_3,
             LEAD(CASE WHEN CITY = 'London' THEN DATETIME END IGNORE NULLS) OVER (PARTITION BY EMP_ID ORDER BY DATETIME) as datetime_3
      FROM MY_TABLE t
     ) t
WHERE CITY = 'London' AND CITY_2 <> 'London' AND CITY_3 = 'London';

Here is a db<>fiddle.

Another option is to use aggregate function as following:

SELECT T.EMP_ID, 
       MAX(CASE WHEN MINRN = RANK_CITY THEN CITY END) AS CITY_1,
       MAX(CASE WHEN MINRN = RANK_CITY THEN DATETIME END) AS DATE_TIME_1,
       MAX(CASE WHEN MINRN + 1 = RANK_CITY THEN CITY END) AS CITY_2,
       MAX(CASE WHEN MINRN + 1 = RANK_CITY THEN DATETIME END) AS DATE_TIME_2,
       MAX(CASE WHEN CNTCITY = 2 and CITY= 'London' THEN CITY END) AS CITY_3,
       MAX(CASE WHEN CNTCITY = 2 and CITY ='London' THEN DATETIME END) AS DATE_TIME_3
FROM (SELECT t.*,
             Min(CASE WHEN CITY = 'London' THEN RANK_CITY END) OVER (PARTITION BY EMP_ID) as MINRN,
             SUM(CASE WHEN CITY = 'London' THEN 1 END) OVER (PARTITION BY EMP_ID ORDER BY DATETIME) AS CNTCITY,
             Max(CASE WHEN CITY = 'London' THEN RANK_CITY END) OVER (PARTITION BY EMP_ID) as MAXRN
      FROM MY_TABLE t
     ) t
WHERE MAXRN - MINRN > 1
GROUP BY EMP_ID

Db<>fiddle demo

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