我想创建一些关于我的用户的统计信息。
我想根据他们年龄的间隔对他们进行分组,并根据他们的性别加以总结。所以最后得到一张这样的表:
age | male | female | total
0-18 | 2 | 1 | 3
18-25 | 3 | 4 | 7
25-100 | 13 | 25 | 38
total | 18 | 30 | 48
(顺便说一下,这些是示例间隔)
右键我是通过为每一行运行此查询来执行此操作:
SELECT
SUM(IF(gender = 'male', 1,0)) AS `male`,
SUM(IF(gender = 'female', 1,0)) AS `female`,
COUNT(gender) AS `total`
FROM `users`
WHERE
`birthday`
BETWEEN
DATE_SUB(CURDATE(), INTERVAL 25 YEAR)
AND
DATE_SUB(CURDATE(), INTERVAL 18 YEAR)
并通过我的php脚本对结果进行求和,以创建最后一行
如何组合所有这些查询来提高性能,也可以通过mysql创建最后一行。
我想要使用的间隔是:
0-18
18-25
25-31
31-36
36-41
41-46
46-51
51-56
56-61
61-100
编辑: 这是一个包含一些样本数据的表的转储,以测试它http://pastebin.com/ytcuu2ge
答案 0 :(得分:2)
SELECT Age,
SUM(gender = 'female') Female,
SUM(gender = 'male') Male,
COUNT(*) TotalPerson
FROM
(
SELECT CASE
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 0 AND 18 THEN '00-18'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 19 AND 25 THEN '19-25'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 26 AND 31 THEN '26-31'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 32 AND 36 THEN '32-36'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 37 AND 41 THEN '37-41'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 42 AND 46 THEN '42-46'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 47 AND 51 THEN '47-51'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 52 AND 56 THEN '52-56'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 57 AND 61 THEN '57-61'
WHEN FLOOR(DATEDIFF(CURDATE(), birthday) / 365) BETWEEN 62 AND 100 THEN '62-100'
END Age,
Gender
FROM users
) ageList
GROUP BY Age
输出
╔════════╦════════╦══════╦═════════════╗
║ AGE ║ FEMALE ║ MALE ║ TOTALPERSON ║
╠════════╬════════╬══════╬═════════════╣
║ 00-18 ║ 0 ║ 1 ║ 1 ║
║ 19-25 ║ 6 ║ 5 ║ 11 ║
║ 26-31 ║ 22 ║ 4 ║ 26 ║
║ 32-36 ║ 39 ║ 16 ║ 56 ║
║ 37-41 ║ 20 ║ 11 ║ 31 ║
║ 42-46 ║ 31 ║ 6 ║ 38 ║
║ 47-51 ║ 18 ║ 3 ║ 21 ║
║ 52-56 ║ 11 ║ 6 ║ 17 ║
║ 57-61 ║ 10 ║ 6 ║ 16 ║
║ 62-100 ║ 12 ║ 12 ║ 24 ║
╚════════╩════════╩══════╩═════════════╝
使用WITH ROLLUP
╔════════╦════════╦══════╦═════════════╗
║ AGE ║ FEMALE ║ MALE ║ TOTALPERSON ║
╠════════╬════════╬══════╬═════════════╣
║ 00-18 ║ 0 ║ 1 ║ 1 ║
║ 19-25 ║ 6 ║ 5 ║ 11 ║
║ 26-31 ║ 22 ║ 4 ║ 26 ║
║ 32-36 ║ 39 ║ 16 ║ 56 ║
║ 37-41 ║ 20 ║ 11 ║ 31 ║
║ 42-46 ║ 31 ║ 6 ║ 38 ║
║ 47-51 ║ 18 ║ 3 ║ 21 ║
║ 52-56 ║ 11 ║ 6 ║ 17 ║
║ 57-61 ║ 10 ║ 6 ║ 16 ║
║ 62-100 ║ 12 ║ 12 ║ 24 ║
║ TOTAL ║ 169 ║ 70 ║ 241 ║
╚════════╩════════╩══════╩═════════════╝
答案 1 :(得分:1)
您可以使用年龄段的“表格”进行非等值连接:
SELECT
AgeRange.Age,
SUM(gender = 'male') AS `male`,
SUM(gender = 'female') AS `female`,
SUM(friends) AS `friends`,
COUNT(gender) AS `total`
FROM `users`
INNER JOIN (
SELECT 0 AS Low, 18 AS High, '0-18' AS Age
UNION SELECT 18, 25, '18-25'
UNION SELECT 25, 31, '25-31'
UNION SELECT 31, 36, '31-36'
UNION SELECT 36, 41, '36-41'
UNION SELECT 41, 46, '41-46'
UNION SELECT 46, 51, '46-51'
UNION SELECT 51, 56, '51-56'
UNION SELECT 56, 61, '56-61'
UNION SELECT 61, 100, '61-100') AgeRange
ON users.birthday BETWEEN
DATE_SUB(CURDATE(), INTERVAL AgeRange.High YEAR) AND
DATE_SUB(CURDATE(), INTERVAL AgeRange.Low YEAR)
GROUP BY AgeRange.Age WITH ROLLUP;
WITH ROLLUP
将包含总计行。有一个SQL小提琴here。
答案 2 :(得分:0)
如果您有静态间隔
,则可以使用UNION ALLSELECT * FROM
((SELECT
'0-18' AS age,
SUM(IF(gender = 'male', 1,0)) AS `male`,
SUM(IF(gender = 'female', 1,0)) AS `female`,
COUNT(gender) AS `total`
FROM users AS u
WHERE `birthday` BETWEEN DATE_SUB(CURDATE(), INTERVAL 18 YEAR)
AND DATE_SUB(CURDATE(), INTERVAL 0 YEAR))
UNION ALL
(SELECT
'18-25' AS age,
SUM(IF(gender = 'male', 1,0)) AS `male`,
SUM(IF(gender = 'female', 1,0)) AS `female`,
COUNT(gender) AS `total`
FROM users AS u
WHERE `birthday` BETWEEN DATE_SUB(CURDATE(), INTERVAL 25 YEAR)
AND DATE_SUB(CURDATE(), INTERVAL 18 YEAR))
UNION ALL
(SELECT
'25-100' AS age,
SUM(IF(gender = 'male', 1,0)) AS `male`,
SUM(IF(gender = 'female', 1,0)) AS `female`,
COUNT(gender) AS `total`
FROM users AS u
WHERE `birthday` BETWEEN DATE_SUB(CURDATE(), INTERVAL 100 YEAR)
AND DATE_SUB(CURDATE(), INTERVAL 25 YEAR))) as l
group by age