Соединение с одним и тем же столом дважды с разными условиями - PullRequest
0 голосов
/ 01 марта 2019

У меня есть таблица, которая содержит летнюю активность пользователей в наборе продуктов на каждый день.Теоретически в кортеже <UserId, Product, Client, Date> имеется только одна строка, так как эта таблица генерируется GROUP BY.Давайте назовем это UserActivity.

UserActivity:

UserId | Product | Client     | Date
------------------------------------------
John   | Bank    | Mobile App | 2019-02-28
John   | Bank    | Desktop App| 2019-02-28
Sally  | Gym     | Web App    | 2019-02-28

У меня есть другая таблица, назовем ее FirstLastSeen, где у нас есть UserId s и когда они впервые использовалиськаждый Product и Client.

FirstLastSeen:

UserId | Product | Client     | Date
------------------------------------------
John   | Bank    | Mobile App | 2019-01-01
John   | Bank    | Desktop App| 2019-02-28
Sally  | Gym     | Web App    | 2019-02-28

Я хочу вычислить, является ли пользователь «новичком» в этом Product И если они новички в этомClient.Это означает, что день, когда они впервые использовали этот Product, равен Date, а дата, когда они впервые использовали этот Product И Client, равен Date.Итак, вот такая таблица:

UserId | Product | Client     | Date       | IsNewProduct | IsNewClient
-----------------------------------------------------------------
John   | Bank    | Mobile App | 2019-02-28 | False        | False        // Used on 01-01
John   | Bank    | Desktop App| 2019-02-28 | False        | True         // First time used this client was same day         
Sally  | Bank    | Mobile App | 2019-02-28 | True         | True         // First time we saw her in this product and client

Один из способов сделать это:

SELECT 
    UA.UserId, 
    UA.Product, 
    UA.Client, 
    CASE FLS.Date = UA.DATE THEN True ELSE FALSE END AS FirstSeenClient
FROM UserActivity as UA
LEFT JOIN FirstLastSeen AS FLS 
    ON  UA.UserId=FLS.UserId 
    AND UA.Product=FLS.Product 
    AND UA.Client=FLS.Client;

Это даст мне FirstSeenClient, что я хочу.Там гарантированно будет строка, соответствующая их использованию.Я не знаю, как получить FirstSeenProduct.Я подозреваю, что ответ находится в подзапросе или оконных функциях, но я не уверен, как написать это, потенциально MIN(Date) OVER (PARTITION BY UserId, Product).Я очень новичок в Windowing Functions, но это даст мне самое раннее Date, которое пользователь видел в этом Product, а затем я смогу сделать еще один SELECT, чтобы проверить Date?Будет ли оконная функция проверять, совпадает ли UserId, Product со строкой, по которой она рассчитывается?

1 Ответ

0 голосов
/ 01 марта 2019

Ваш запрос пока выглядит хорошо.Чтобы проверить, использует ли продукт клиент впервые, вы можете использовать ROW_NUMBER(), чтобы присвоить ранг каждой записи в группах записей, имеющих одинаковые UserId и одинаковые Product, упорядоченные по Date.Когда номер строки 1, вы знаете, что имеете дело с новым продуктом.

SELECT 
    UA.UserId, 
    UA.Product, 
    UA.Client, 
    CASE 
        WHEN ROW_NUMBER() OVER(PARTITION BY UA.UserId, UA.Product ORDER BY UA.Date) = 1 
        THEN true 
        ELSE false 
    END AS IsNewProduct,
    CASE 
        WHEN UA.Date = FLS.Date
        THEN true
        ELSE false
    END AS IsNewClient
FROM UserActivity as UA
LEFT JOIN FirstLastSeen AS FLS 
    ON UA.UserId   = FLS.UserId 
    AND UA.Product = FLS.Product 
    AND UA.Client  = FLS.Client;

Это демонстрация на DB Fiddle с вашими примерами данныхвозвращает:

| UserId | Product | Client      | IsNewProduct | IsNewClient |
| ------ | ------- | ----------- | ------------ | ----------- |
| John   | Bank    | Mobile App  | 1            | 0           |
| John   | Bank    | Desktop App | 0            | 1           |
| Sally  | Gym     | Web App     | 1            | 1           |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...