MySQL GROUP CONCAT дублирует - PullRequest
       4

MySQL GROUP CONCAT дублирует

0 голосов
/ 23 февраля 2012

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

score_id, uid, af_id, level, record_date

Где uid - это идентификатор пользователя в системе. af_id - это фокус, на котором был установлен уровень. af_id будет либо 1,1, 1,2, 1,3. Level - целочисленное значение в диапазоне от 3 до 7.

Пример набора данных будет:

1, 2, 1.1, 4, 2012-09-02
2, 2, 1.2, 4, 2012-09-02
3, 2, 1.3, 3, 2012-09-02
4, 2, 1.3, 4, 2012-11-30

Мне нужно запросить базу данных, чтобы узнать, какой уровень достиг пользователь для каждого af_id между определенными датами. Я использую GROUP_CONCAT, чтобы привести данные в один ряд. Мой запрос работает в течение первого периода времени, но после этого выдает дубликаты. Мой SQL до сих пор:

SELECT u.uid, u.forename, u.surname, ui.gender, GROUP_CONCAT(us.level ORDER BY us.af_id SEPARATOR ',') AS levels
FROM users u
LEFT OUTER JOIN user_scores us
ON us.uid=u.uid AND us.record_date > '2012-09-01' AND us.record_date < '2012-10-20'
JOIN user_info ui ON ui.uid =u.uid
GROUP BY u.uid
ORDER BY u.surname ASC

Это дает результат:

Joe Bloggs  M  4,4,3

Я хочу расширить месяцы, чтобы мой запрос мог возвращать обновленные результаты для af_id. Так что, если я расширю результаты, они будут варьироваться между 2012-09-01 и 2012-12-31. Я хотел бы видеть следующие результаты:

Joe Bloggs  M  4,4,4

Однако мой запрос (с использованием вышеуказанного SQL) возвращает следующий результат:

Joe Bloggs  M  4,4,3,4

Любая помощь с этим была бы очень признательна. Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 23 февраля 2012

Похоже, вы получаете результаты для каждого af_id по чистому совпадению - в вашем примере данных ровно одна строка соответствует вашему заданному диапазону дат для каждого af_id.Вам нужно сначала сгруппировать по uid, af_id, чтобы получить уровень, я думаю, здесь вам нужен самый высокий, поэтому MAX () подойдет.

SELECT u.uid, u.forename, u.surname, ui.gender, GROUP_CONCAT(us.level ORDER BY us.af_id ) AS levels
FROM users u
LEFT OUTER JOIN
( SELECT  uid, af_id, MAX(level) as level
  FROM user_scores 
  WHERE record_date > '2012-09-01' AND record_date < '2012-12-31'
  GROUP BY uid, af_id ) us
ON us.uid=u.uid
JOIN user_info ui ON ui.uid =u.uid
GROUP BY u.uid
ORDER BY u.surname ASC
0 голосов
/ 23 февраля 2012

Пересмотренный запрос. Вы заявляете, что он должен быть в состоянии восстановить историческое, и звучит так, будто вы просто заинтересованы в достижении самого высокого уровня. Для этого внутреннему запросу просто нужно ограничить максимальную дату для user_scores, и он может просто получить uid, af_id и MAX (уровень).

Затем его можно присоединить к users u, и, в свою очередь, GROUP_CONCAT может вернуть вам фокусы и их соответствующие максимальные баллы. Если дополнительный фокус будет добавлен позже, он будет возвращен.

Это не вернет фокус 1.2, если у пользователя нет очков в фокусе 1.2

SELECT 
    u.uid, 
    u.forename, 
    u.surname, 
    ui.gender,
    GROUP_CONCAT(us.af_id) AS focusOrder,
    GROUP_CONCAT(us.level ORDER BY us.af_id ASC) AS focusMaxLevels
FROM users u

INNER JOIN user_info ui 
    ON ui.uid =u.uid

INNER JOIN (
    SELECT
        uid,
        af_id,
        MAX(level) as level
    FROM user_scores
    WHERE record_date <= DATE('2012-10-20')
    GROUP BY uid, af_id
    ORDER BY uid ASC, af_id ASC 
) AS us
ON us.uid = u.uid
GROUP BY u.uid
ORDER BY u.surname ASC
...