В SQL Есть ли способ построить переменную, которая отслеживает исторические данные в нескольких группах? - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть вопросы по поводу «переменной конструкции» в SQL, точнее, Большого запроса в GCP (Google Cloud Platform). У меня нет глубокого понимания SQL, поэтому мне трудно манипулировать и конструировать переменные, которые я собираюсь сделать. Таким образом, любой комментарий будет очень признателен.

Я думаю о создании двух переменных, что мне кажется довольно сложным. Я хотел бы кратко представить структуру этого набора данных, прежде чем я узнаю о способе построения этих переменных. Этот набор данных является историческим рекордом игровых матчей, сыгранных около 25 000 пользователей, на общую сумму около 100 миллионов матчей. 10 игроков участвуют в одном матче, и каждый игрок выбирает своего героя. Из-за технической проблемы я могу манипулировать этими двумя переменными и создавать их только через Большой запрос в GCP (Google Cloud Platform).

Создание переменной «Любимый герой»

Во-первых, я планирую создать переменную «любимый герой» на уровне матча. Как показано в таблицах ниже, базовыми переменными являются: 1) match_id (который определяет каждое совпадение) 2) user_id (который указывает каждого пользователя) 3) день (который указывает дату сыгранного матча) 4) hero_type (который указывает, какой герой сделал каждый игрок (пользователь) выбирает). Позвольте мне прояснить, что я собираюсь построить. Как показано ниже, пользователь «3258 (синий)» сыграл четыре раза за период наблюдения. Таким образом, для четвертого матча пользователя 3258 его / ее любимый hero_type - 36, потому что его / ее совокупный любимый here_type - 36. Обратите внимание, что «совокупный» не включает тот самый день. Например, пользователь «2067 (красный)» сыграл три раза: 20190208, 20190209, 20190212. Каждый раз игрок выбирал героев 81, 81 и 34 соответственно. Таким образом, «favour_hero» в третий раз равен 81, а не 34. Кроме того, я бы хотел установить число fav_hero, равное 2. Важно отметить, что существуют последовательные, но разделенные таблицы, как показано ниже. Хотя эти таблицы разделены, временная шкала не должна быть прекращена, а должна быть связана друг с другом.

enter image description here

Построение переменной «Знакомство»

Я думаю, что вторая переменная, которую я собираюсь сделать, более хитрая, чем предыдущая. Я планирую создать переменную met_before, которая будет подсчитывать общее количество случаев, когда каждый пользователь встречался с другим игроком (ами). Например, в match_id 2 пользователь 3258 (синий) и 2067 (красный) ранее встречался друг с другом в match_id 1. Таким образом, каждый пользователь имеет значение 1 для переменной «met_before». Итак, концепция «match_id» ”Особенно становится более важным при создании этой переменной, чем предыдущая, потому что эта переменная в основном создается на основе match_id. Другой пример: для match_id 5 пользователь 3258 (синий) имеет значение 4 для переменной «met_before», потому что игрок встречался с пользователем 2386 (зеленый) два раза (match_id 1 и 3) и с пользователем 2067 ( красный) для двух раз (match_id 1 и 2) соответственно. Опять же, важно отметить, что существуют последовательные, но разделенные таблицы, как показано ниже. Хотя эти таблицы разделены, временную шкалу не следует прекращать, а связывать друг с другом.

enter image description here

1 Ответ

1 голос
/ 12 апреля 2020

Как указано в комментариях, было бы лучше, если бы вы могли предоставить пример данных. Также в этом вопросе есть 2 отдельные проблемы. Для них было бы лучше создать 2 разных потока.

Я подготовил примеры данных из ваших скриншотов и необходимый вам код. Таким образом, вы можете попробовать код и дать отзыв в соответствии с выводом. Так что, если что-то не так, мы можем повторить.

CREATE TEMP FUNCTION find_fav_hero(heroes ARRAY<INT64>) AS 
((
  SELECT STRING_AGG(CAST(hero as string) ORDER BY hero)
  FROM (
    SELECT *, max(cnt) over () as max_cnt
    FROM (
      SELECT hero, count(*) as cnt
      FROM UNNEST(heroes) as hero
      GROUP BY 1
    )
  )
  WHERE cnt = max_cnt
));

WITH 
rawdata as (
  SELECT 2386 AS user_id, 20190208 as day, 30 as hero_type UNION ALL
  SELECT 3268 AS user_id, 20190208 as day, 30 as hero_type UNION ALL
  SELECT 2067 AS user_id, 20190208 as day, 81 as hero_type UNION ALL
  SELECT 3268 AS user_id, 20190209 as day, 36 as hero_type UNION ALL
  SELECT 2067 AS user_id, 20190209 as day, 81 as hero_type UNION ALL
  SELECT 2386 AS user_id, 20190210 as day, 3 as hero_type UNION ALL
  SELECT 3268 AS user_id, 20190210 as day, 36 as hero_type UNION ALL
  SELECT 2386 AS user_id, 20190212 as day, 203 as hero_type UNION ALL
  SELECT 3268 AS user_id, 20190212 as day, 36 as hero_type UNION ALL
  SELECT 2067 AS user_id, 20190212 as day, 34 as hero_type
)
SELECT *, 
  count(*) over (partition by user_id order by day) - 1 as met_before,
  find_fav_hero(array_agg(hero_type) over (partition by user_id order by day rows between unbounded preceding and 1 preceding )) as favourite_hero
from rawdata
order by day, user_id
...