Как избежать повторных вхождений в столбце - PullRequest
1 голос
/ 05 ноября 2019

У меня есть таблица, которая описывает агента, который заказывает билеты для разных клиентов. следующие данные описывают данные одного клиента.

enter image description here

Из приведенных выше данных я ожидаю enter image description here

Конечный смысл в том, что я хочу сгруппировать очереди: сначала он забронировал билеты в Сингапур, затем в Остин, снова в Сингапур и Дели.

Как мы можем достичь этого в SQL, помогите мне в этом

, если out out похож на следующее, также полезно enter image description here

Ответы [ 4 ]

1 голос
/ 05 ноября 2019

Это пробелы и проблема острова. Чтобы ее решить, нужно сгенерировать группы смежных записей. Обычно это делается путем сравнения номеров строк по двум разным разделам.

Обратите внимание:

select 
    agent_id,   
    travel_destination,
    min(date_of_booking) first_date_of_booking,
    max(date_of_booking) max_date_of_booking
from (
    select 
        t.*,
        row_number() 
            over(partition by agent_id order by date_of_booking) rn1,
        row_number() 
            over(partition by agent_id, travel_destination order by date_of_booking) rn2
    from mytable t
) t 
group by 
    agent_id, 
    rn1 - rn2,
    travel_destination
order by first_date_of_booking

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

Еще одно замечание: на основании ваших выборочных данных неясно, хотите ли вы поместить customerid в группу;Я предположил, что нет (если да, вам нужно добавить этот столбец в оба раздела).

Демонстрация по БД Fiddle :

Учитывая это (упрощенный) набор данных:

agent_id | travel_destination | customer_id | date_of_booking
:------- | :----------------- | :---------- | :--------------
A1001    | Singapore          | C1001       | 2019-06-10     
A1001    | Singapore          | C1001       | 2019-06-11     
A1001    | Austin             | C1001       | 2019-06-12     
A1001    | Singapore          | C1001       | 2019-06-13     
A1001    | Singapore          | C1001       | 2019-06-14     
A1001    | Dehli              | C1001       | 2019-06-15     

Запрос возвращает:

agent_id | travel_destination | first_date_of_booking | max_date_of_booking
:------- | :----------------- | :-------------------- | :------------------
A1001    | Singapore          | 2019-06-10            | 2019-06-11         
A1001    | Austin             | 2019-06-12            | 2019-06-12         
A1001    | Singapore          | 2019-06-13            | 2019-06-14         
A1001    | Dehli              | 2019-06-15            | 2019-06-15         

Чтобы получить второй вывод, который вы продемонстрировали, вы можете добавить еще один уровень агрегирования и использовать string_agg()

select 
    agent_id,
    string_agg(travel_destination order by first_date_of_booking) travel_destination
from (
  -- above query
) t
group by agent_id
0 голосов
/ 05 ноября 2019

Я бы просто использовал lag():

SELECT t.agent_id, t.travel_dest
FROM (SELECT t.*,
             LAG(travel_dest) OVER (PARTITION BY agent_id ORDER BY bookdt) as prev_travel_dest
      FROM t
     ) t
WHERE prev_travel_dest IS NULL OR prev_travel_dest <> travel_dest
ORDER BY agent_id, bookdt;

Я не могу придумать более простого решения.

0 голосов
/ 05 ноября 2019

Ниже для стандартного SQL BigQuery

#standardSQL
SELECT agent_id, 
  STRING_AGG(DISTINCT travel_destination) AS travel_destination
FROM `project.dataset.table`
GROUP BY agent_id    

он выдаст следующий вывод

Row agent_id    travel_destination   
1   A1001       Singapore,Austin,Delhi      

Похоже, ожидаемый результат равен Singapore,Austin,Singapore,Delhi - ниже еще один вариант для этого

#standardSQL
CREATE TEMP FUNCTION DedupConsecutive(line STRING) RETURNS STRING LANGUAGE js AS """
  return line.split(",").filter(function(value,index,arr){return value != arr[index+1];}).join(",");
""";
SELECT agent_id, 
  DedupConsecutive(STRING_AGG(travel_destination ORDER BY date_of_booking)) destinations
FROM `project.dataset.table`
GROUP BY agent_id   

Те же чувства, что и у Гордона - I cannot think of a simpler solution.: o)

0 голосов
/ 05 ноября 2019

Попробуйте - по крайней мере, если в вашей базе данных есть функция, подобная LISTAGG, как в Vertica ...

WITH
-- this is your input - next time put it in so it can be 
-- copy-pasted and formatted to the below ....                                                                                                                                                    
input(agent_id,travel_dest,cust_id,bookdt) AS (
          SELECT 'A1001','Singapore','C1001',DATE '2109-06-10'
UNION ALL SELECT 'A1001','Singapore','C1001',DATE '2019-06-11'
UNION ALL SELECT 'A1001','Austin'   ,'C1001',DATE '2019-06-19'
UNION ALL SELECT 'A1001','Austin'   ,'C1001',DATE '2019-06-19'
UNION ALL SELECT 'A1001','Austin'   ,'C1001',DATE '2019-06-20'
UNION ALL SELECT 'A1001','Singapore','C1001',DATE '2019-07-30'
UNION ALL SELECT 'A1001','Singapore','C1001',DATE '2019-07-31'
UNION ALL SELECT 'A1001','Delhi'    ,'C1001',DATE '2019-08-01'
UNION ALL SELECT 'A1001','Delhi'    ,'C1001',DATE '2019-08-10'
UNION ALL SELECT 'A1001','Delhi'    ,'C1001',DATE '2019-08-10'
UNION ALL SELECT 'A1001','Delhi'    ,'C1001',DATE '2019-08-10'
UNION ALL SELECT 'A1001','Delhi'    ,'C1001',DATE '2019-08-10'
UNION ALL SELECT 'A1001','Delhi'    ,'C1001',DATE '2019-08-25'
)
-- real WITH clause starts here - substitute comma below with "WITH" ...
,
with_prev AS (
  SELECT
    agent_id
  , travel_dest
  , LAG(travel_dest,1,'') OVER (PARTITION BY agent_id ORDER BY bookdt) AS prev_dest
  FROM input
)
,
de_duped AS (
  SELECT
    agent_id
  , travel_dest
   FROM with_prev
   WHERE travel_dest <> prev_dest
)
SELECT
  agent_id
, LISTAGG(travel_dest) AS travel_dest
FROM de_duped
GROUP BY 1
;

Вы получите:

 agent_id |                travel_dest                 
----------+--------------------------------------------
 A1001    | Singapore,Austin,Singapore,Delhi,Singapore                                                                                                  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...