按年龄和性别选择

时间:2014-07-21 08:39:57

标签: php mysql sql

我做了以下查询,按年龄组选择人数,作为计数和百分比。年龄在我的数据库中存储为0000-00-00

SELECT  AgeGroup, count(*) AS count, ROUND(sum( 100 ) / total) AS percentage
        FROM    (
        SELECT  case
                when  age between 0 and 17 then '00 - 17'
                when  age between 18 and 24 then '18 − 24'
                when  age between 25 and 34 then '25 − 34'
                when  age between 35 and 44 then '35 − 44'
                when  age between 45 and 54 then '45 − 54'
                when  age between 55 and 64 then '55 − 64'
                when  age between 65 and 125 then '65+'
                else 'Unknown'
                end AS AgeGroup
        FROM    (
                SELECT  ROUND(DATEDIFF(Cast(NOW() as Date),
                            Cast(dateofbirth as Date)) / 365, 0) as age
                FROM    people
                ) as SubQueryAlias
        ) as SubQueryAlias2
        CROSS JOIN (SELECT count( * ) AS total FROM people)x
        group by
        AgeGroup

目前的结果是:

AgeGroup | count | percentage
00 - 17    33      1
18 − 24    235     5
..         ..      ..

我需要的是添加查询以分隔男性/女性/未知结果:

AgeGroup  | gender | count | percentage
00 - 17     M        33      1
00 - 17     F        33      1
..          ..       ..      ..

2 个答案:

答案 0 :(得分:1)

我真的希望我错了......但不断出错的原因是......你没有选择性别?

另外,一个书呆子的旁注,365天不能一年,它大约365.25天XD这意味着你的等式稍微偏离哈哈

SELECT  AgeGroup, gender, count(*) AS count, ROUND(sum( 100 ) / total) AS percentage
    FROM    (
    SELECT  case
            when  age between 0 and 17 then '00 - 17'
            when  age between 18 and 24 then '18 − 24'
            when  age between 25 and 34 then '25 − 34'
            when  age between 35 and 44 then '35 − 44'
            when  age between 45 and 54 then '45 − 54'
            when  age between 55 and 64 then '55 − 64'
            when  age between 65 and 125 then '65+'
            else 'Unknown'
            end AS AgeGroup, gender
    FROM    (
            SELECT  ROUND(DATEDIFF(Cast(NOW() as Date),
                        Cast(dateofbirth as Date)) / 365, 0) as age, 
                        gender
            FROM    people
            ) as SubQueryAlias
    ) as SubQueryAlias2
    CROSS JOIN (SELECT count( * ) AS total FROM people)x
    group by
    AgeGroup, gender

答案 1 :(得分:1)

您可以通过定义范围表来获得最简单的时间。这也可以防止您需要对每个条目进行日期数学运算,因此可能更有效地进行分组。

首先,年龄范围表:

SELECT '00 - 17' AS ageGroup, CURRENT_DATE AS lower, CURRENT_DATE - INTERVAL 18 YEAR AS upper
UNION ALL
SELECT '18 - 24', CURRENT_DATE - INTERVAL 18 YEAR, CURRENT_DATE - INTERVAL 25 YEAR
UNION ALL
SELECT '25 - 34', CURRENT_DATE - INTERVAL 25 YEAR, CURRENT_DATE - INTERVAL 35 YEAR
UNION ALL
SELECT '35 - 44', CURRENT_DATE - INTERVAL 35 YEAR, CURRENT_DATE - INTERVAL 45 YEAR
UNION ALL
SELECT '45 - 54', CURRENT_DATE - INTERVAL 45 YEAR, CURRENT_DATE - INTERVAL 55 YEAR
UNION ALL
SELECT '55 - 64', CURRENT_DATE - INTERVAL 55 YEAR, CURRENT_DATE - INTERVAL 65 YEAR
UNION ALL
SELECT '65+', CURRENT_DATE - INTERVAL 65 YEAR, null
UNION ALL
SELECT 'Unknown', null, null

SQL FIddle Demo

...它会生成一个关于你期望的表格。请注意,上限是独占的,这就是它使用与下一行的下限相同的值的原因。另请注意:1)'65+'括号没有上限,2)'Unknown'括号没有上限。

当然,我们还需要一个Gender表:

SELECT 'M' AS gender
UNION ALL
SELECT 'F'
UNION ALL
SELECT 'Unknown'

(作为旁注,我通常使用多行VALUES(...)语句,但是由于某种原因,SQL Fiddle似乎不喜欢MySQL子查询中的语法。请使用您认为合适的语句。 )

我们需要最后一项知识:
具体而言,COUNT(<expression>)将忽略null行。因此,我们可以将完整查询拼接在一起,类似于:

SELECT AgeRange.ageGroup, Gender.gender, 
       COUNT(People.id), ROUND(100 * COUNT(People.id) / Total.countOfPeople) AS percentage
FROM (SELECT '00 - 17' AS ageGroup, CURRENT_DATE AS lower, CURRENT_DATE - INTERVAL 18 YEAR AS upper
      UNION ALL
      SELECT '18 - 24', CURRENT_DATE - INTERVAL 18 YEAR, CURRENT_DATE - INTERVAL 25 YEAR
      UNION ALL
      SELECT '25 - 34', CURRENT_DATE - INTERVAL 25 YEAR, CURRENT_DATE - INTERVAL 35 YEAR
      UNION ALL
      SELECT '35 - 44', CURRENT_DATE - INTERVAL 35 YEAR, CURRENT_DATE - INTERVAL 45 YEAR
      UNION ALL
      SELECT '45 - 54', CURRENT_DATE - INTERVAL 45 YEAR, CURRENT_DATE - INTERVAL 55 YEAR
      UNION ALL
      SELECT '55 - 64', CURRENT_DATE - INTERVAL 55 YEAR, CURRENT_DATE - INTERVAL 65 YEAR
      UNION ALL
      SELECT '65+', CURRENT_DATE - INTERVAL 65 YEAR, null
      UNION ALL
      SELECT 'Unknown', null, null)  AgeRange
CROSS JOIN (SELECT 'M' AS Gender
            UNION ALL
            SELECT 'F'
            UNION ALL 
            SELECT 'Unknown') Gender
CROSS JOIN (SELECT COUNT(*) countOfPeople
            FROM People) Total
LEFT JOIN People
       ON ((People.dateOfBirth > AgeRange.upper AND dateOfBirth <= AgeRange.lower)
           OR (People.dateOfBirth <= AgeRange.lower AND AgeRange.upper IS NULL)
           OR (AgeRange.lower IS NULL AND AgeRange.upper IS NULL AND People.dateOfBirth IS NULL))
          AND (Gender.gender = People.gender
               OR Gender.gender = 'Unknown' AND People.gender IS NULL)
GROUP BY AgeRange.ageGroup, Gender.gender

SQL Fiddle Demo
(请注意,小提琴演示使用此帖子的日期'2014-07-21'作为CURRENT_DATE,以便为将来的读者提供稳定的年龄范围查询。)