按SQL中的一系列值进行分组

时间:2011-03-11 19:51:11

标签: sql sql-server

我的表格如下:

id | label_id | value
1  | 1        | 500
2  | 1        | 600
3  | 1        | 900
4  | 1        | 10000
5  | 1        | 300
6  | 2        | ...
....................

现在,我想生成一个查询结果,例如:

caption        | count
Less than 500  | 1
500 to 900     | 2
Above 900      | 1

简而言之,我正在尝试对结果集进行分区,以便按一系列值进行分组。 有什么想法吗?

分区组显然是预先定义的,这意味着我提前知道我的分区方案应该是:< 500,500至900,900 +等等。

谢谢!

5 个答案:

答案 0 :(得分:15)

select sum(case when value < 500 then 1 else 0 end) as [less than 500],
       sum(case when value >= 500 and value <= 900 then 1 else 0 end) as [500 to 900],
       sum(case when value > 900 then 1 else 0 end) as [above 900]
    from YourTable

编辑:从下面的评论中解决Dalen's问题,并提供问题中给出的确切格式的输出:

select 'less than 500' as Caption, count(*) as Count
    from YourTable
    where value < 500
union all
select '500 to 900' as Caption, count(*) as Count
    from YourTable
    where value >= 500 and value <= 900
union all
select 'above 900' as Caption, count(*) as Count
    from YourTable
    where value > 900

而且,对于SQL Server 2005+,您可以通过将UNPIVOT与原始查询一起使用来改进这一点:

select Caption, Count
    from (select sum(case when value < 500 then 1 else 0 end) as [less than 500],
                 sum(case when value >= 500 and value <= 900 then 1 else 0 end) as [500 to 900],
                 sum(case when value > 900 then 1 else 0 end) as [above 900]
              from YourTable) t
unpivot (Count for Caption in ([less than 500], [500 to 900], [above 900])) p

答案 1 :(得分:4)

我会介绍另一个名为_range的表,类似于:

label     |lower|upper  |
-------------------------
up to 500 |0    |500    |
500 to 1k |501  |1000   |
over 1k   |1001 |1000000|

你可以加入你的桌子(我的例子中是_data)来得到像你问的那样:

SELECT _range.label,COUNT(*) AS count
FROM _range JOIN _data
   ON value >= lower and value <= upper
GROUP BY _range.label

结果将是

label     |count|
-----------------
up to 500 |2    |
500 to 1k |2    |
over 1k   |1    |

答案 2 :(得分:1)

select case when  value < 500 then 'Less than 500'
                when value >= 500 and value <= 900 then '500 - 900'
                else 'Above 900' end as caption, COUNT(*) as count
    from mytable
    group by case when  value < 500 then 'Less than 500'
                when value >= 500 and value <= 900 then '500 - 900'
                else 'Above 900' end

答案 3 :(得分:0)

尝试:

select count(*) from TABLE where VALUE_FIELD between VALUE1 and VALUE2

run it for different value ranges.

答案 4 :(得分:0)

对于SQL Server 2000,我们没有Unpivot .....它仍然只有一次扫描..

SELECT 

 CASE WHEN T1.Group = 1 Then 'less than 500'
      WHEN T1.Group = 2 Then '500 to 900'
      WHEN T1.Group = 3 Then 'above 900' END as [Label],

 CASE WHEN T1.Group = 1 Then T.[less than 500]
      WHEN T1.Group = 2 Then T.[500 to 900]
      WHEN T1.Group = 3 Then T.[above 900] END as [Count]

FROM
(
  select sum(case when value < 500 then 1 else 0 end) as [less than 500],
         sum(case when value >= 500 and value <= 900 then 1 else 0 end) as [500 to 900],
         sum(case when value > 900 then 1 else 0 end) as [above 900]
    from YourTable
) T
CROSS JOIN 
(
   Select 1 as Group
    UNION ALL
   Select 2
    UNION ALL
   Select 3
) T1