how can we group 5 pm yesterday to 5 pm today records to todays date

后端 未结 2 2011
醉梦人生
醉梦人生 2021-01-23 23:11

oracle table

id  timestamp                status
1  2019-10-20 12:34:56.000   approved
1  2019-10-22 12:34:56.000   approved
2  2019-10-20 17:34:56.000   approv         


        
相关标签:
2条回答
  • 2021-01-23 23:40

    If you want to treat 5pm to 5pm as the "same" day, it is easy to shift an Oracle date either forward or backward with fractions of day, (eg 5pm can be shifted 7 hours forward to become the start of the 'next' day)

    SQL> create table ora_table (id number, time_data timestamp, status varchar2(30));
    
    Table created.
    
    SQL> insert into ora_table values (1  , to_timestamp('2019-10-20 12:34:56.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'approved');
    
    1 row created.
    
    SQL> insert into ora_table values (1  , to_timestamp('2019-10-22 12:34:56.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'approved');
    
    1 row created.
    
    SQL> insert into ora_table values (2  , to_timestamp('2019-10-20 17:34:56.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'approved');
    
    1 row created.
    
    SQL> insert into ora_table values (2  , to_timestamp('2019-10-21 12:34:56.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'approved');
    
    1 row created.
    
    SQL> insert into ora_table values (3  , to_timestamp('2019-10-23 18:10:10.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'mod_in_ip');
    
    1 row created.
    
    SQL> insert into ora_table values (3  , to_timestamp('2019-10-24 11:10:10.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'approved');
    
    1 row created.
    
    SQL> insert into ora_table values (3  , to_timestamp('2019-10-24 12:10:10.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'approved');
    
    1 row created.
    
    SQL> insert into ora_table values (4  , to_timestamp('2019-10-25 12:10:10.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'approved');
    
    1 row created.
    
    SQL> insert into ora_table values (4  , to_timestamp('2019-10-25 18:10:10.000', 'yyyy-mm-dd hh24:mi:ss.ff'), 'approved');
    
    1 row created.
    
    SQL>
    SQL> select id, time_data, trunc(time_data) true_date, trunc(time_data+7/24) mapped_date
      2  from ora_table;
    
            ID TIME_DATA                          TRUE_DATE MAPPED_DA
    ---------- ---------------------------------- --------- ---------
             1 20-OCT-19 12.34.56.000000 PM       20-OCT-19 20-OCT-19
             1 22-OCT-19 12.34.56.000000 PM       22-OCT-19 22-OCT-19
             2 20-OCT-19 05.34.56.000000 PM       20-OCT-19 21-OCT-19 <===
             2 21-OCT-19 12.34.56.000000 PM       21-OCT-19 21-OCT-19
             3 23-OCT-19 06.10.10.000000 PM       23-OCT-19 24-OCT-19 <===
             3 24-OCT-19 11.10.10.000000 AM       24-OCT-19 24-OCT-19
             3 24-OCT-19 12.10.10.000000 PM       24-OCT-19 24-OCT-19
             4 25-OCT-19 12.10.10.000000 PM       25-OCT-19 25-OCT-19
             4 25-OCT-19 06.10.10.000000 PM       25-OCT-19 26-OCT-19
    
    9 rows selected.
    
    0 讨论(0)
  • 2021-01-23 23:55

    This should give you what you're looking for:

    WITH cte(id, ts, NewCutoff, Row_Num) AS (
      select 
        id, 
        ts, 
        MIN(
          trunc(ts) + 
          CASE 
            WHEN EXTRACT(HOUR FROM ts) < 17 THEN INTERVAL '00 17' DAY TO HOUR
            ELSE INTERVAL '01 17' DAY TO HOUR -- If time is after 5pm, add an extra day
          END
        ) OVER(PARTITION BY id) AS NewCutoff, -- Determine cut-off TS for "new" entries
        ROW_NUMBER() OVER(
          PARTITION BY id ORDER BY ts DESC
        ) AS Row_Num -- Order entries by date within "id" group
      FROM mytable
    )
    SELECT id, CASE WHEN ts < NewCutoff THEN 'new' ELSE 'edited' END AS prefix
    FROM cte
    WHERE Row_Num = 1 -- Only look at latest entry per id
    ;
    

    You may need to check the end conditions -- i.e. how to handle a ts value with exactly 5pm.

    SQL Fiddle

    0 讨论(0)
提交回复
热议问题