我有一个名为user_scores的表,如下所示:
id | af_id | uid | level | record_date
----------------------------------------
1 | 1.1 | 1 | 3 | 2012-01-01
2 | 1.1 | 1 | 4 | 2012-02-01
3 | 1.2 | 1 | 3 | 2012-01-01
4 | 1.2 | 1 | 5 | 2012-03-01
...
我有另一个表调用user_info,如下所示:
uid | forename | surname | gender
-----------------------------------
1 | Homer | Simpson | M
2 | Marge | Simpson | F
3 | Bart | Simpson | M
4 | Lisa | Simpson | F
...
在用户分数中,uid是系统上注册用户的用户ID,af_id标识用户提交的特定测试。每个测试的用户得分在1到5之间,可以每月提交。
我的问题是我需要在年底进行分析,以计算达到特定测试每个级别的用户数量。分析是为了显示男性和女性的性别分歧。
因此,例如,管理员将选择测试1.1,系统将生成基于年度中每个用户达到的总MAX水平的COUNT的统计数据,并进行性别分割。
非常感谢任何帮助。提前谢谢。
-
我想我需要澄清一下自己。由于用户可以在一年中多次完成测试,因此同一测试将有多个分数。查询应采用达到的最高级别并将其包括在计数中。示例结果将是:
Male Results:
level1 | level2 | level3 | level4 | level5
------------------------------------------
2 | 5 | 10 | 8 | 1
答案 0 :(得分:2)
我不确定我到底是什么意思,但我一如既往地走了。据我了解,您想知道每个性别中有多少人在某一年达到了每个级别。
SELECT MaxLevel,
COUNT(CASE WHEN ui.Gender = 'M' THEN 1 END) AS Males,
COUNT(CASE WHEN ui.Gender = 'F' THEN 1 END) AS Females
FROM User_Info ui
INNER JOIN
( SELECT MAX(Level) AS MaxLevel,
UID
FROM User_Scores us
WHERE af_ID = '1.1'
AND YEAR(Record_Date) = 2012
GROUP BY UID
) AS MaxUs
ON MaxUs.uid = ui.UID
GROUP BY MaxLevel
我已在SQL Fiddle上提供了一些示例数据,因此您可以看到它是否是您所追求的。
修改强> 要转置数据,以便级别位于行顶部,而性别位于行中,则以下内容将起作用:
SELECT Gender,
COUNT(CASE WHEN MaxLevel = 1 THEN 1 END) AS Level1,
COUNT(CASE WHEN MaxLevel = 2 THEN 1 END) AS Level2,
COUNT(CASE WHEN MaxLevel = 3 THEN 1 END) AS Level3,
COUNT(CASE WHEN MaxLevel = 4 THEN 1 END) AS Level4,
COUNT(CASE WHEN MaxLevel = 5 THEN 1 END) AS Level5
FROM User_Info ui
INNER JOIN
( SELECT MAX(Level) AS MaxLevel,
UID
FROM User_Scores us
WHERE af_ID = '1.1'
AND YEAR(Record_Date) = 2012
GROUP BY UID
) AS MaxUs
ON MaxUs.uid = ui.UID
GROUP BY Gender
注意,如果有超过5个级别,则需要向select语句添加更多内容,或者开始构建动态SQL。
答案 1 :(得分:2)
假设record_date
只保留日期(没有时间部分):
SELECT
s.maxlevel,
COUNT(NULLIF(gender, 'F')) AS M,
COUNT(NULLIF(gender, 'M')) AS F
FROM user_info u
INNER JOIN (
SELECT
uid,
MAX(level) AS maxlevel
FROM user_scores
WHERE record_date > DATE_SUB(CURDATE(), INTERVAL DAYOFYEAR(CURDATE()) DAY)
AND af_id = '1.1'
GROUP BY
uid
) s ON s.uid = u.uid
GROUP BY
s.maxlevel
这将只显示user_scores
表中找到的最高级别。如果您有一个Levels
表,其中列出了所有可能的级别(1到5),则可以使用该表来获取完整的级别列表。如果请求的数据子集中没有某些级别,则相应的行将在两列中显示0
。
以上是上面的脚本,稍加修改以显示完整的关卡图表:
SELECT
l.level AS maxlevel,
COUNT(NULLIF(gender, 'F')) AS M,
COUNT(NULLIF(gender, 'M')) AS F
FROM user_info u
INNER JOIN (
SELECT
uid, MAX(level) AS maxlevel
FROM user_scores
WHERE record_date > DATE_SUB(CURDATE(), INTERVAL DAYOFYEAR(CURDATE()) DAY)
AND af_id = '1.1'
GROUP BY
uid
) s ON s.uid = u.uid
RIGHT JOIN Levels l ON s.maxlevel = l.level
GROUP BY
l.level
答案 2 :(得分:0)
根据您的编辑进行编辑。
select sum(if(a.gender="M",1,0)) Male_users, sum(if(a.gender="F",1,0)) Female_users
from myTable a where
a.level = (select max(b.level) from myTable b where a.uid=b.uid)
group by af_id.
我匆匆打字。但它应该工作或至少让你到达你需要去的地方。例如。如果您需要指定时间范围,请添加。
答案 3 :(得分:0)
希望这是你想要的!
按用户ID显示记录组数,并为af_id'1.1'显示最高得分的性别。
select count(*), info.uid, info.gender, max(score.level)
from user_info as info
join user_scores as score
on info.uid = score.uid
where score.af_id = '1.1'
group by info.uid, info.gender;
答案 4 :(得分:-2)
你需要像
这样的东西SELECT
uid,
MAX(level)
WHERE
record_date BETWEEN '2012-01-01' AND '2012-12-31'
AND af_id='1.1'
GROUP BY uid
如果您需要性别拆分,那么根据您每个性别需要的统计信息,您可以在user_info表中将JOIN添加到此查询中(以获得每性别的MAX)以将其包装为子查询和JOIN on整件事。