Чтобы извлечь несколько ключевых строк данных из пользовательского сеанса, я пытаюсь обработать результаты подзапроса с помощью последующей агрегации group by
, но я обнаружил, что один из моих столбцов изподзапрос не переносится.
У меня есть три таблицы: одна - набор user_actions
, который можно отслеживать в веб-приложении, другая содержит user_events
экземпляров указанного действия и третья - player_keys
, содержит идентификаторы сеанса, которые используются для привязки нескольких user_events к одному сеансу.
Из-за необычного способа определения user_actions
определенный экземпляр user_action
иногда идентифицируется с помощью quantity
значение, которое передается вместе с ним, и иногда каждый возможный результат имеет свой собственный user_action
.
Так, учитывая серию user_actions
...
+----+-------------------+-------------+
| id | NAME | campaign_id |
+----+-------------------+-------------+
| 15 | Theme Vote Age | 301 |
| 18 | Theme Vote Gender | 301 |
| 20 | Theme 5 Selected | 301 |
+----+-------------------+-------------+
... Iиметь user_events
вот так
+---------------+----------------+----------+---------------------+
| player_key_id | user_action_id | quantity | created_at |
+---------------+----------------+----------+---------------------+
| 123 | 15 | 50 | 2019-10-11 12:34:56 |
| 123 | 18 | 2 | 2019-10-11 12:34:57 |
| 123 | 20 | 1 | 2019-10-11 12:34:58 |
+---------------+----------------+----------+---------------------+
Мой запрос представляет собой двухэтапный процесс с помощью подзапроса: сначала я запрашиваю идентификаторы ключей игрока и номер голоса темы в подзапросе, а затем соединяю его с другим запросом, которыйищет другие строки FИз этих идентификаторов ключей игрока (т.е. пользовательских сессий) добавить в два других поля, которые я хочу (переписать, чтобы использовать синтаксис INNER JOIN
, как я думаю, Гордон предложил в [своем комментарии], ( Агрегированные результаты подзапроса в MySQL don ')t сохраните одно из моих полей ), используйте оператор CASE
согласно Эрику и удалите лишнее соединение в таблице player_keys
, для tcadidot ):
SELECT ue.player_key_id, vd.theme_vote,
max(if(ua.name = 'Theme Vote Age', quantity, 0)) as theme_age,
max(if(ua.name = 'Theme Vote Gender', quantity, 0)) as theme_gender
FROM user_events AS ue
INNER JOIN user_actions ua
ON ua.id = ue.user_action_id
INNER JOIN (
SELECT ue.player_key_id AS player_key_id,
max(CASE ua.name
WHEN 'Theme 1 Selected' THEN 1
WHEN 'Theme 2 Selected' THEN 2
WHEN 'Theme 3 Selected' THEN 3
WHEN 'Theme 4 Selected' THEN 4
WHEN 'Theme 5 Selected' THEN 5
ELSE 6
END) as theme_vote
FROM user_events ue
INNER JOIN user_actions ua
ON ue.user_action_id = ua.id
WHERE ua.campaign_id = 301
AND ua.name LIKE 'Theme % Selected'
AND date(ue.created_at) = current_date
GROUP BY ue.player_key_id
) vd
ON ue.player_key_id = vd.player_key_id
WHERE (ua.name = 'Theme Vote Age' OR ua.name = 'Theme Vote Gender')
GROUP BY ue.player_key_id
HAVING theme_age > 1 AND theme_age < 100 AND theme_gender != 3;
Я думаю, что внутренний запрос GROUP BY
необходим, потому что каждый сеанс, сгруппированный по player_key_id
, содержит один набор данных голосования по теме (включая тот, который соответствует выбранной теме%). Внешний запрос снова группируется по player_key_id
, потому что каждая сессия содержит один «Возраст голосования по темам» и «Пол голоса по темам» user_action
, который я просмотрел и получил две строки для каждой сессии.
То, что я ожидаю получить обратно, это что-то вроде
+---------------+------------+-----------+--------------+
| player_key_id | theme_vote | theme_age | theme_gender |
+---------------+------------+-----------+--------------+
| 123 | 5 | 50 | 2 |
+---------------+------------+-----------+--------------+
| 163 | 1 | 37 | 1 |
+---------------+------------+-----------+--------------+
| 748 | 2 | 28 | 1 |
+---------------+------------+-----------+--------------+
Но я получаю обратно
+---------------+------------+-----------+--------------+
| player_key_id | theme_vote | theme_age | theme_gender |
+---------------+------------+-----------+--------------+
| 123 | 6 | 50 | 2 |
+---------------+------------+-----------+--------------+
| 163 | 6 | 37 | 1 |
+---------------+------------+-----------+--------------+
| 748 | 6 | 28 | 1 |
+---------------+------------+-----------+--------------+
Так что, в общем-то, что-то превращается theme_vote
в 6 черезвсе группировки. Мой подзапрос сам по себе работает нормально. Он возвращает строки, подобные ожидаемым, где theme_vote
охватывает 1-6:
+---------------+------------+
| player_key_id | theme_vote |
+---------------+------------+
| 123 | 5 |
+---------------+------------+
| 724 | 2 |
+---------------+------------+
| 833 | 3 |
+---------------+------------+
| 298 | 2 |
+---------------+------------+
| 529 | 6 |
+---------------+------------+
Выполнение этого в разные дни возвращает разные объемы данных, предполагая, что работает фильтр даты, и фильтр campaign_id
также успешен.
Количество строк, возвращаемых подзапросом, также значительно меньше, чем весь запрос.
См. здесь: fiddle: https://www.db -fiddle.com / f /8U2WoHG7tzimFbEZP956kq / 0
Для дальнейшего пояснения я использую GROUP BY
во внешнем запросе, чтобы превратить это:
+---------------+------------+-----------+--------------+
| player_key_id | theme_vote | theme_age | theme_gender |
+---------------+------------+-----------+--------------+
| 12160443 | 1 | 33 | 0 |
| 12160443 | 1 | 0 | 2 |
+---------------+------------+-----------+--------------+
... в это:
+---------------+------------+-----------+--------------+
| player_key_id | theme_vote | theme_age | theme_gender |
+---------------+------------+-----------+--------------+
| 12160443 | 1 | 33 | 2 |
+---------------+------------+-----------+--------------+