我有一个结果表,如下所示:
score_id, uid, af_id, level, record_date
其中uid
是系统上用户的用户ID。 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
对此的任何帮助将不胜感激。提前谢谢。
答案 0 :(得分:2)
似乎您通过纯巧合得到每个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
答案 1 :(得分:0)
修改后的查询。你说它应该能够检索历史性的,并且听起来你只对所达到的最高水平感兴趣。为此,内部查询只需要限制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