SQL: Функция окна после соединения

#mysql #sql

Вопрос:

У меня есть две таблицы: Подписки и Товары:

Подписки (sub_id PK, идентификатор пользователя, значение)
Загрузки (идентификатор загрузки PK, идентификатор пользователя, идентификатор категории)

Моя цель-получить таблицу результатов формы (идентификатор пользователя, значение sum_subscription_value, num_download_categories). Другими словами: каждая строка уникальна для идентификатора пользователя, в котором общая стоимость подписок, приобретенных пользователем, указана вместе с количеством категорий, из которых пользователь загрузил вещи.

Я попытался решить проблему с помощью следующего кода, но категории подсчитываются неправильно. Я думаю, что проблема может быть в соединении, так как строки значений повторяются, но я не уверен, как точно обойти проблему. Любая помощь будет признательна

 SELECT 
    DISTINCT subscriptions.user_id, 
    SUM(value) OVER (PARTITION by subscriptions.user_id, category_id) AS user_purchases,
    COUNT(category_id) OVER (PARTITION by subscriptions.user_id) AS user_downloads
FROM subscriptions
LEFT JOIN downloads on subscriptions.user_id = downloads.user_id;
 

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

1. Суммируйте каждую таблицу по идентификатору пользователя, а затем соедините эти два подзапроса.

2. …функция окна не требуется. Возможно, потребуется полное внешнее присоединение, если вы можете загружать файлы без подписки…

Ответ №1:

Моя цель-получить таблицу результатов формы (идентификатор пользователя, значение sum_subscription_value, num_download_categories).

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

Вместо этого вы можете использовать union all и group by :

 select user_id,
       sum(value) as subscription_value,
       count(distinct category_id) as num_categories
from ((select user_id, value, null as category_id
       from subscriptions
      ) union all
      (select user_id, NULL as value, category_id
       from downloads
      )
     ) sd
group by user_id;