0

我想创建一些关于我的用户的统计信息。

我想根据他们的年龄间隔对他们进行分组,并根据他们的性别进行总结。所以最后我得到了一张这样的桌子:

   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

SQL Fiddle 架构

4

3 回答 3

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 ║
╚════════╩════════╩══════╩═════════════╝
于 2013-04-07T05:06:34.193 回答
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 Fiddle 。

于 2013-04-07T05:13:10.077 回答
0

如果您有静态间隔,您可以使用 UNION ALL

SELECT * 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

SQL 小提琴演示

于 2013-04-07T05:08:58.000 回答