0

If time difference for 'Login_Date' column with records for same Department is within 18 hours then pick only the record with earliest login date.

Below sample data:

enter image description here

Need query for below data:

enter image description here

MT0
  • 143,790
  • 11
  • 59
  • 117
  • 1
    Can you please share what have you done so far in order to solve the problem by using sample data as text, but not images. – Barbaros Özhan May 17 '22 at 14:17
  • Does this answer your question? [Oracle SQL query: Retrieve latest values per group based on time](https://stackoverflow.com/questions/2000908/oracle-sql-query-retrieve-latest-values-per-group-based-on-time) – astentx May 17 '22 at 16:24
  • @astentx No, it is not asking for the first row of each group. It is asking to exclude rows that are within 18 hours of a previous row. – MT0 May 17 '22 at 18:43

2 Answers2

1

From Oracle 12, you can use MATCH_RECOGNIZE to do row-by-row processing if you want to exclude all rows that are within 18 hours of the first row of the group:

SELECT *
FROM   table_name
MATCH_RECOGNIZE (
  PARTITION BY department
  ORDER     BY login_date
  ALL ROWS PER MATCH
  PATTERN (first_row {- within_18_hours* -} )
  DEFINE
    within_18_hours AS login_date <= first_row.login_date + INTERVAL '18' HOUR
)

Which, for the sample data:

CREATE TABLE table_name (record_id, department, "USER", login_date) AS
SELECT 1, 'IT',      'xujk', DATE '2022-01-10' + INTERVAL '10' HOUR FROM DUAL UNION ALL
SELECT 2, 'IT',      'jkl',  DATE '2022-01-10' + INTERVAL '15' HOUR FROM DUAL UNION ALL
SELECT 3, 'IT',      'xujk', DATE '2022-01-12' + INTERVAL '11' HOUR FROM DUAL UNION ALL
SELECT 4, 'FINANCE', 'mno',  DATE '2022-01-10' + INTERVAL '01' HOUR FROM DUAL UNION ALL
SELECT 5, 'FINANCE', 'abc',  DATE '2022-01-12' + INTERVAL '15' HOUR FROM DUAL UNION ALL
SELECT 6, 'FINANCE', 'def',  DATE '2022-01-12' + INTERVAL '20' HOUR FROM DUAL;

Outputs:

DEPARTMENT LOGIN_DATE RECORD_ID USER
FINANCE 10-JAN-22 4 mno
FINANCE 12-JAN-22 5 abc
IT 10-JAN-22 1 xujk
IT 12-JAN-22 3 xujk

If you want to exclude rows that are within 18 hours of the previous row (and not necessarily within 18 hours of the earliest row of the group) then you can use:

SELECT *
FROM   table_name
MATCH_RECOGNIZE (
  PARTITION BY department
  ORDER     BY login_date
  ALL ROWS PER MATCH
  PATTERN (first_row {- within_18_hours* -} )
  DEFINE
    within_18_hours AS login_date <= PREV(login_date) + INTERVAL '18' HOUR
)

db<>fiddle here

MT0
  • 143,790
  • 11
  • 59
  • 117
0

Try this:

Select Record_ID,d.Department,User,d.Login_Date
from data d
inner join ( Select Department,min(Login_Date) 
             from data 
             where EXTRACT(HOUR FROM CAST(Login_Date AS timestamp)) <= 18
             group by Department,trunc(Login_Date) ) as t
on d.Department= t.Department and d.Login_Date = t.Login_Date
Walid
  • 718
  • 5
  • 13