Объединение двух строк в таблице в Oracle с одинаковыми деталями, кроме даты вступления в силу - PullRequest
0 голосов
/ 16 мая 2018

У меня есть таблица Customer с четырьмя столбцами ниже

customer_id customer_effective_date customer_term_date service
1           1/1/2017                1/31/2017          Bike
1           2/1/2017                12/31/2017         Bike
1           1/1/2018                1/31/2018          Car
1           2/1/2018                2/28/2018          Car
1           3/1/2018                3/31/2018          Bike
1           4/1/2018                4/30/2018          Bike

Я пытаюсь объединить их, как показано ниже:

1           1/1/2017                12/31/2017          Bike
1           1/1/2018                2/28/2018          Car
1           3/1/2018                4/30/2018          Bike

Может кто-нибудь подсказать, как нам этого добиться. я попытался сгруппировать и взять минимальные и максимальные даты, но так как сервис для первой записи - Bike, я получаю результат как

1           1/1/2017                4/30/2017         Bike
1           1/1/2018                2/28/2018          Car

Мне нужен какой-то хедсэп, как мы можем это сделать.

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Это проблема разрыва и островов.Я не уверен, какова реальная логика (должны ли даты перекрываться, как в вопросе?), Но один из подходов - это разница в номерах строк:

select customer_id,
       min(customer_effective_date),
       max(customer_term_date),
       service
from (select t.*,
             row_number() over (partition by customerid order by customer_effective_date) as seqnum,
             row_number() over (partition by customerid, service order by customer_effective_date) as seqnum_s
      from t
     ) t
group by customer_id, (seqnum_s - seqnum), service
order by 2;
0 голосов
/ 16 мая 2018

Это даст желаемый результат, если вы также сгруппируете по году:

SQL Fiddle

Настройка схемы Oracle 11g R2 :

CREATE TABLE table_name (
  customer_id,
  customer_effective_date,
  customer_term_date,
  service
) AS
SELECT 1, DATE '2017-01-01', DATE '2017-01-31', 'Bike' FROM DUAL UNION ALL
SELECT 1, DATE '2017-02-01', DATE '2017-12-31', 'Bike' FROM DUAL UNION ALL
SELECT 1, DATE '2018-01-01', DATE '2018-01-31', 'Car' FROM DUAL UNION ALL
SELECT 1, DATE '2018-02-01', DATE '2018-02-28', 'Car' FROM DUAL UNION ALL
SELECT 1, DATE '2018-03-01', DATE '2018-03-31', 'Bike' FROM DUAL UNION ALL
SELECT 1, DATE '2018-04-01', DATE '2018-04-30', 'Bike' FROM DUAL;

Запрос 1 :

SELECT customer_id,
       MIN( customer_effective_date ) AS customer_effective_date,
       MAX( customer_term_date ) AS customer_term_date,
       service
FROM   table_name
GROUP BY
       customer_id,
       service,
       TRUNC( customer_effective_date, 'YYYY' )
ORDER BY
       customer_effective_date

Результаты

| CUSTOMER_ID | CUSTOMER_EFFECTIVE_DATE |   CUSTOMER_TERM_DATE | SERVICE |
|-------------|-------------------------|----------------------|---------|
|           1 |    2017-01-01T00:00:00Z | 2017-12-31T00:00:00Z |    Bike |
|           1 |    2018-01-01T00:00:00Z | 2018-02-28T00:00:00Z |     Car |
|           1 |    2018-03-01T00:00:00Z | 2018-04-30T00:00:00Z |    Bike |

Запрос 2 :

Это также объединит группы, если это проблема островков и разрывов, и сделает это без агрегации:

SELECT *
FROM   (
  SELECT customer_id,
         LAST_VALUE( customer_effective_date )
           IGNORE NULLS OVER (
             PARTITION BY customer_id, service
             ORDER BY COALESCE( customer_effective_date, customer_term_date )
           ) AS customer_effective_date,
         customer_term_date,
         service
  FROM   (
    SELECT customer_id,
           CASE
           WHEN customer_effective_date
                  = LAG( customer_term_date, 1 ) OVER (
                      PARTITION BY customer_id, service
                      ORDER BY customer_effective_date
                    ) + 1
           THEN NULL
           ELSE customer_effective_date
           END AS customer_effective_date,
           CASE
           WHEN customer_term_date
                  = LEAD( customer_effective_date, 1 ) OVER (
                      PARTITION BY customer_id, service
                      ORDER BY customer_effective_date
                    ) - 1
           THEN NULL
           ELSE customer_term_date
           END AS customer_term_date,
           service
    FROM   table_name
  )
)
WHERE  customer_term_date IS NOT NULL
ORDER BY customer_effective_date

Результаты

| CUSTOMER_ID | CUSTOMER_EFFECTIVE_DATE |   CUSTOMER_TERM_DATE | SERVICE |
|-------------|-------------------------|----------------------|---------|
|           1 |    2017-01-01T00:00:00Z | 2017-12-31T00:00:00Z |    Bike |
|           1 |    2018-01-01T00:00:00Z | 2018-02-28T00:00:00Z |     Car |
|           1 |    2018-03-01T00:00:00Z | 2018-04-30T00:00:00Z |    Bike |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...