Есть ли способ группировать значения, получая только те, которые проверяют определенное условие?

#sql #oracle #oracle11g

#sql #Oracle #oracle11g

Вопрос:

Я пытаюсь написать запрос в Oracle SQL, который объединяет значения по некоторым идентификаторам, где у меня есть следующая таблица в качестве входных данных:

ID SOME_DATE RANK_POSITION
301 20211201 1
301 20211202 2
301 20211203 3
649 20211201 1
649 20211202 2
649 20211206 3
649 20211208 4
649 20211211 5
758 20211212 1
758 20211222 2

И вы хотите получить что-то вроде этого:

ID FIRST_IN_RANK_DATE SECOND_IN_RANK_DATE
301 01/12/2021 02/12/2021
649 01/12/2021 02/12/2021
758 12/12/2021 22/12/2021

Где FIRST_IN_RANK_DATE — это дата, которая является первой в RANK_POSITION для ID , и SECOND_IN_RANK_DATE это дата, которая является второй RANK_POSITION для конкретного ID .

Комментарии:

1. Посмотрите pivot или conditional aggregation

Ответ №1:

Вы можете использовать условную агрегацию:

 SELECT id,
       MAX(CASE rank_position WHEN 1 THEN some_date END) AS first_in_rank_date,
       MAX(CASE rank_position WHEN 2 THEN some_date END) AS second_in_rank_date
FROM   table_name
GROUP BY id
 

Или PIVOT :

 SELECT *
FROM   table_name
PIVOT (
  MAX(some_date)
  FOR rank_position IN (
    1 AS first_in_rank_date,
    2 AS second_in_rank_date
  )
)
 

Или, из Oracle 12, MATCH_RECOGNIZE :

 SELECT *
FROM   table_name
MATCH_RECOGNIZE (
  PARTITION BY id
  ORDER     BY rank_position
  MEASURES
    rank1.some_date AS first_in_rank_date,
    rank2.some_date AS second_in_rank_date
  PATTERN ( ^ rank1 rank2 )
  DEFINE
    rank1 AS rank_position = 1,
    rank2 AS rank_position = 2
)
 

Что для образца данных:

 CREATE TABLE table_name (ID, SOME_DATE, RANK_POSITION) AS
SELECT 301, DATE '2021-12-01', 1 FROM DUAL UNION ALL
SELECT 301, DATE '2021-12-02', 2 FROM DUAL UNION ALL
SELECT 301, DATE '2021-12-03', 3 FROM DUAL UNION ALL
SELECT 649, DATE '2021-12-01', 1 FROM DUAL UNION ALL
SELECT 649, DATE '2021-12-02', 2 FROM DUAL UNION ALL
SELECT 649, DATE '2021-12-06', 3 FROM DUAL UNION ALL
SELECT 649, DATE '2021-12-08', 4 FROM DUAL UNION ALL
SELECT 649, DATE '2021-12-11', 5 FROM DUAL UNION ALL
SELECT 758, DATE '2021-12-12', 1 FROM DUAL UNION ALL
SELECT 758, DATE '2021-12-22', 2 FROM DUAL;
 

Весь вывод:

ID FIRST_IN_RANK_DATE SECOND_IN_RANK_DATE
301 2021-12-01 00:00:00 2021-12-02 00:00:00
649 2021-12-01 00:00:00 2021-12-02 00:00:00
758 2021-12-12 00:00:00 2021-12-22 00:00:00

db<>скрипка здесь