Оператор Case над совокупностью строк - PullRequest
0 голосов
/ 14 декабря 2018

Я работаю в Google Big Query со стандартным SQL.

У меня есть данные просмотра страниц.Все, что имеет отношение к делу, это

| user_id | entity_id | url |

URL-адреса будут иметь вид /entities/entity_id/show или entities/entity_id/reply/new

. Пользователь может отображаться совместно с обоими или обоими типами или ни одним из типов URL.и может быть повторен.

Моя цель - таблица, которая выглядит следующим образом

| user_id | entity_id | view_type |

Где view_type это либо "показать", либо "новый"

Тамдолжна быть только одна строка на пару пользователь / сущность.view_type должен быть "новым", если эта пара user_id / entity_id когда-либо появляется вместе даже с одним URL-адресом формы /entities/entity_id/replies/new, но "показывать", если у пары нет "новых" URL-адресов.Если в исходной таблице нет примеров пары user_id / entity_id, то они не должны присутствовать в итоговой таблице.

Я включу оператор with с образцами данных для повторяемости

WITH data AS (
    select 1 as user_id, 23 as entity_id, '/entities/23/replies/new' as url

    UNION ALL

    select 1 as user_id, 23 as entity_id, '/entities/23/show' as url

    UNION ALL

    select 2 as user_id, 30 as entity_id, '/entities/30/show' as url
)
SELECT * from data

При этом создается таблица, подобная этой

| user_id | entity_id |            url             |
----------------------------------------------------
|       1 |        23 | '/entities/23/replies/new' |
|       1 |        23 |        '/entities/23/show' |
|       2 |        30 |        '/entities/30/show' |

Я могу достичь своей цели с помощью двух with операторов, выполняющих select distinct для любого типа URL, затем присоединяясь и выполняяcase оператор, который работает на наличие или отсутствие любого объединения, работающего для данной пары user / entity.

Вот что я имею в виду:

WITH data AS (
    select 1 as user_id, 23 as entity_id, '/entities/23/replies/new' as url

    UNION ALL

    select 1 as user_id, 23 as entity_id, '/entities/23/show' as url

    UNION ALL

    select 2 as user_id, 30 as entity_id, '/entities/30/show' as url
), news AS (
    SELECT DISTINCT user_id, entity_id, 1 as found
    FROM data 
    WHERE url like '%new'
), shows AS (
    SELECT DISTINCT user_id, entity_id, 1 as found 
    FROM data
    WHERE url like '%show'
)
SELECT DISTINCT d.user_id, 
    d.entity_id,
    CASE WHEN n.found = 1 then 'new'
        WHEN s.found = 1 then 'show' end as view_type
FROM data d
LEFT JOIN news n on n.user_id = d.user_id and n.entity_id = d.entity_id
LEFT JOIN shows s on s.user_id = d.user_id and s.entity_id = d.entity_id

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

Мне пришло в голову, что я могу попробовать вставить все URL-адреса для пары user_id / entity_id в массив, а затем работать с массивом с помощью оператора case, который говорит что-то вроде "если есть элементыиз массива совпадения «новый», затем «новый» и т. д.). Но я не уверен, как сделать «любые совпадения регулярных выражений элементов» или, если это вообще возможно.

Буду признателен за любыепонимание, которое может дать каждый!

1 Ответ

0 голосов
/ 14 декабря 2018

Один метод агрегации:

SELECT user_id, entity_id, 
       (CASE WHEN COUNTIF(url like '%new') > 0 THEN 'new' ELSE 'show'
        END) as view_type
FROM data 
GROUP BY user_id, entity_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...