【问题标题】:Create range bins from SQL Server table for histograms从 SQL Server 表中为直方图创建范围箱
【发布时间】:2013-10-06 21:26:02
【问题描述】:

我在 SQL Server 中有下表:

-----------------------------
ID       Age          Gender
1          30           F
2          35           M
3          32           M
4          18           F
5          21           F

我需要做的是执行一个查询,它将给定范围内的记录分组并计算出现次数。结果需要稍后显示在直方图(条形图)中。我尝试了类似于以下的查询:

SELECT 
count(CASE WHEN Age>= 10 AND Age < 20 THEN 1 END) AS '10 - 20',
count(CASE WHEN Age>= 21 AND Age < 30 THEN 1 END) AS '21 - 30',
count(CASE WHEN Age>= 31 AND Age < 35 THEN 1 END) AS '31 - 35',
count(CASE WHEN Age>= 36 AND Age < 40 THEN 1 END) AS '36 - 40',
FROM (SELECT Age FROM Attendees) AS AgeGroups

目前,这可以解决问题,但不考虑性别列。它将产生一个计算每个年龄段的频率的单行:

10-20     21-30     31-35     36-40
  0         22        21        13

如果考虑性别,则应针对每种性别显示两条记录。我需要看到类似的东西:

Gender    10-20     21-30     31-35     36-40
  M         0         12        9         6
  F         0         10        12        7

我应该如何解决这个问题?

【问题讨论】:

标签: sql grouping histogram


【解决方案1】:

只需将Gender 列添加到您的SELECT,然后执行GROUP BY

SELECT 
Gender,
count(CASE WHEN Age>= 10 AND Age < 20 THEN 1 END) AS [10 - 20],
count(CASE WHEN Age>= 21 AND Age < 30 THEN 1 END) AS [21 - 30],
count(CASE WHEN Age>= 31 AND Age < 35 THEN 1 END) AS [31 - 35],
count(CASE WHEN Age>= 36 AND Age < 40 THEN 1 END) AS [36 - 40]
FROM Attendees AS AgeGroups
GROUP BY Gender

【讨论】:

  • 我相信你必须使用 sum() 函数而不是 count() 函数。否则,每个范围将等于参加者表中的记录总数。 (顺便说一句 - 我多次犯过同样的错误。)
  • @ToddMeinershagen 我猜他的桌子每行都有一个唯一的与会者,因为他的示例显示,在这种情况下,COUNTSUM 将工作相同,因为 SUM 没有得到一个值除了每行 1 个
【解决方案2】:

上面的示例不包括值 20、30、35 和 40。 给这只猫剥皮的方法不止一种,这里有一种:

SELECT 
Gender,
count(CASE WHEN Age> 9 AND Age <= 20 THEN 1 END) AS [10 - 20],
count(CASE WHEN Age> 20 AND Age <= 30 THEN 1 END) AS [21 - 30],
count(CASE WHEN Age> 30 AND Age <= 35 THEN 1 END) AS [31 - 35],
count(CASE WHEN Age> 35 AND Age <= 40 THEN 1 END) AS [36 - 40]
FROM Attendees AS AgeGroups
GROUP BY Gender

【讨论】:

    【解决方案3】:

    我最近遇到了一个类似的问题,我需要查看多个变量而不仅仅是一个变量,我的解决方案是使用临时表。

    CREATE TABLE #bin (
        startRange int, 
        endRange int,
        agelabel varchar(10)
    );
    GO
    
    INSERT INTO #bin (startRange, endRange, mylabel) VALUES (10, 20, '10-20')
    INSERT INTO #bin (startRange, endRange, mylabel) VALUES (21, 30, '21-30')
    INSERT INTO #bin (startRange, endRange, mylabel) VALUES (31, 35, '31-35')
    INSERT INTO #bin (startRange, endRange, mylabel) VALUES (36, 40, '36-40')
    GO
    
    SELECT 
        b.agelabel as ageBracket, 
        a.Gender, 
        count(a.Gender) as total
    FROM 
        Attendees a
    INNER JOIN 
        #bin b on (a.Age >= b.startRange and a.Age <= b.EndRange)
    GROUP BY
        b.agelabel, a.Gender
    
    DROP TABLE #bin 
    GO
    

    或者,也可能是更好的解决方案,

    With table1 as
    (
    SELECT 
        CASE 
            WHEN Age >= 10 and Age <= 20 then '10-20'
            WHEN Age > 20 and Age <= 30 then '21-30'
            WHEN Age > 30 and Age <= 35 then '31-35'
            WHEN Age > 35 and Age <= 40 then '36-40'
            ELSE 'NA'
        End as ageBracket,
        Gender
    FROM
        Attendees
    )
    
    SELECT
        ageBracket,
        Gender,
        Count(Gender),
    FROM
        table1
    GROUP BY
        ageBracket, Gender
    

    结果会在哪里:

    AgeBracket Gender Total
    10-20 M 0
    10-20 F 0
    21-30 M 12
    21-30 F 10
    31-35 M  9
    31-35 F 12
    36-40 M  6
    36-40 F  7
    

    您可以使用第一个 select 语句收集您选择的所有数据,同时使用第二个查询执行任何必要的计算。

    我认为这些解决方案对于您的问题可能有点矫枉过正,但由于这是我发现的关于分箱的唯一问题,希望它对其他人有用!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-11
      • 1970-01-01
      相关资源
      最近更新 更多