分组范围

SQL*_*ify 0 sql sql-server sql-server-2008

我有一张包含员工姓名及其供应商经历的表格.我必须创建一个包含以下数据的表

给我的数据就像

empname vendor experience
a        1
b        2
c        10
d        11
e        20
f        12
g        21
h        22
Run Code Online (Sandbox Code Playgroud)

我想生成一个SQL查询来显示这样的数据

vendor_experience(months)   count
0-6                          2
0-12                         5
0-18                         5
more                         8
Run Code Online (Sandbox Code Playgroud)

请帮我查询.

Nik*_*vić 5

您可以使用case语句来获取独占范围的计数:

select case when [vendor experience] <= 6 then '0-6'
            when [vendor experience] <= 12 then '0-12'
            when [vendor experience] <= 18 then '0-18'
            else 'more'
        end [vendor_experience(months)],
       count (*) [count]
  from experiences
 group by
       case when [vendor experience] <= 6 then '0-6'
            when [vendor experience] <= 12 then '0-12'
            when [vendor experience] <= 18 then '0-18'
            else 'more'
        end
Run Code Online (Sandbox Code Playgroud)

这会产生与您相同的结果(包含范围):

; with ranges as 
  (
    select 6 as val, 0 as count_all
    union all
    select 12, 0
    union all
    select 18, 0
    union all
    select 0, 1
  )
select case when ranges.count_all = 1
            then 'more'
            else '0-' + convert (varchar(10), ranges.val) 
        end [vendor_experience(months)],
       sum (case when ranges.count_all = 1 
                   or experiences.[vendor experience] <= ranges.val 
                 then 1 end) [count]
  from experiences
 cross join ranges
 group by ranges.val, ranges.count_all
Run Code Online (Sandbox Code Playgroud)

count_all 设置为1以标记开放范围.

Sql Fiddle就在这里.

更新:尝试解释.

with以结束括号开头和结尾的第一部分称为CTE.有时它被称为inline view因为它可以在同一查询中多次使用,并且在某些情况下是可更新的.在这里,它用于准备范围的数据并适当命名ranges.此名称用于主查询.Val是范围的最大值,count_all如果范围没有上端(18 +,更多,或者您希望调用它),则为1.数据行通过union all组合.您可以仅在括号之间复制/粘贴部分,并仅运行它以查看结果.

主体experiences使用交叉连接将范围连接到范围.这将创建来自experiences和的所有行的组合ranges.对于行d 11,将有4行,

empname vendor experience val count_all
d       11                  6 0
d       11                 12 0
d       11                 18 0
d       11                  0 1
Run Code Online (Sandbox Code Playgroud)

选择列表中的第一个case语句通过检查count_all生成标题 - 如果它是1,则输出more,否则使用高范围值构造标题.第二个案例陈述使用sum(1)计数.由于聚合函数忽略空值,并且如果没有找到匹配,则没有其他的情况评估为null,只需检查count_all是否为真(意味着经验中的这一行在此范围内计算)或者是否vendor experience小于或等于上限当前范围的范围值.在上面的示例中,第一个范围不计入11,但是将计入所有其余范围.

然后按val和count_all对结果进行分组.为了更好地了解它是如何工作的,您可以删除group by和sum()并在聚合之前查看数字.按empname排序,val将有助于查看[count]的值如何根据员工的不同val变化.

注意:我用我目前的英语水平做到了最好.如果您需要一个(或两个,或您需要的多个),请不要犹豫要求澄清.