简体   繁体   中英

Oracle SQL - Creating a view that groups data by timestamp range

I have a table that contains song's names, their genres and the date when they were added.

I'd like to create a view which groups these table's records based on their timestamps. Each group should include records that were inserted at most one second later than the first record of the group.

Here's an example of my table:


    +------+----------+-------+-------------------------+
    | ID   | name     | genre | date_added              |
    +------+----------+-------+-------------------------+
    |    1 | aaaa     | aaaa  | 21/05/21 14:21:54,010   |
    |    2 | bbb      | bbbb  | 21/05/21 14:21:54,020   |
    |    3 | qqq      | cccc  | 21/05/21 14:21:54,500   |
    |    4 | ccc      | dddd  | 21/05/21 14:22:00,000   |
    |    5 | www      | eeee  | 21/05/21 14:22:01,000   |
    |    6 | s        | ffff  | 21/05/21 14:23:00,000   |
    +------+----------+-------+-------------------------+

Here's an example of the expected view:


    +------+-------------+----------+------------------------+
    | ID   | first_genre | ids      | first_date             |
    +------+-------------+----------+------------------------+
    |    1 | aaaa        | [1,2,3]  | 21/05/21 14:21:54,010  |
    |    2 | dddd        | [4,5]    | 21/05/21 14:21:54,020  |
    |    3 | qqq         | [6]      | 21/05/21 14:21:54,500  |
    +------+-------------+----------+------------------------+

What I'm trying to do is select a record, get its date_added column, then proceed to check the consecutive records to see if they are within a 1 second range from the record that was just selected. If they are, it gets added to this group. Otherwise, I start a new group.

I haven't found a similar solution that creates a list like the one I wanted to, so that's why I'm asking this question. I'm a beginner at both SQL and Oracle SQL, so I don't know how to properly work with timestamp ranges, especially if grouping is involved.

Any help would be really appreciated.

You can't truncate timestamp up to the second, but you can cast it to date. The precision of date is seconds so any fractional seconds will be truncated.

CREATE TABLE test_data(id, sname, genre, date_added) AS
(
SELECT 1, 'aaaa', 'aaaa', TO_TIMESTAMP('21/05/21 14:21:54,010','DD/MM/YY HH24:MI:SS,FF3') FROM DUAL UNION ALL
SELECT 2, 'bbb',  'bbbb', TO_TIMESTAMP('21/05/21 14:21:54,010','DD/MM/YY HH24:MI:SS,FF3') FROM DUAL UNION ALL
SELECT 3, 'qqq',  'cccc', TO_TIMESTAMP('21/05/21 14:21:54,500','DD/MM/YY HH24:MI:SS,FF3') FROM DUAL UNION ALL
SELECT 4, 'ccc',  'dddd', TO_TIMESTAMP('21/05/21 14:22:00,000','DD/MM/YY HH24:MI:SS,FF3') FROM DUAL UNION ALL
SELECT 5, 'www',  'eeee', TO_TIMESTAMP('21/05/21 14:22:01,000','DD/MM/YY HH24:MI:SS,FF3') FROM DUAL UNION ALL
SELECT 6, 's',    'ffff', TO_TIMESTAMP('21/05/21 14:22:01,000','DD/MM/YY HH24:MI:SS,FF3') FROM DUAL
);


CREATE OR REPLACE VIEW genre_list_by_date (
  date_added,
  id_list,
  first_genre
) AS
  SELECT
    cast(date_added as date),
    LISTAGG(id, ', ') WITHIN GROUP(ORDER BY id)              AS id_list,
    MIN(genre)     AS first_genre
    FROM
    test_data
   GROUP BY
    cast(date_added as date);

select 
  TO_CHAR(date_added,'DD/MM/YY HH24:MI:SS'), 
  id_list, 
  first_genre 
  from genre_list_by_date;



date_added          id_list  first_genre

21/05/21 14:21:54   1, 2, 3  aaaa
21/05/21 14:22:00   4        dddd
21/05/21 14:22:01   5, 6     eeee

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