您可以使用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
这会产生与您相同的结果(包括范围):
; 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
count_all
设置为 1 以标记开放式结束范围。
Sql Fiddle 在这里。
更新:尝试解释。
以右括号开头with
和结尾的第一部分称为CTE。有时它被称为是inline view
因为它可以在同一个查询中多次使用,并且在某些情况下是可更新的。在这里,它用于为范围准备数据,并适当地命名为ranges
. 此名称用于主查询。Val
是范围的最大值,count_all
如果范围没有上限(18+,更多,或者您希望调用它),则为 1。数据行通过union all进行组合。您可以仅在括号之间复制/粘贴部分并运行它以查看结果。
主体使用交叉连接experiences
将表与范围连接起来。这将创建来自和的所有行的组合。对于行,将有 4 行,experiences
ranges
d 11
empname vendor experience val count_all
d 11 6 0
d 11 12 0
d 11 18 0
d 11 0 1
选择列表中的第一个 case 语句通过检查 count_all 来生成标题 - 如果它是一个,则输出more
,否则使用上限值构造标题。第二个 case 语句使用 sum(1) 计数。由于聚合函数忽略空值,并且如果没有找到匹配项,则没有 else 的情况评估为空,因此检查 count_all 是否为真(意味着经验中的这一行在此范围内计数)或是否vendor experience
小于或等于上限就足够了当前量程的量程值。在上面的示例中,第一个范围不计入 11,但将计入所有其余范围。
然后按 val 和 count_all 对结果进行分组。为了更好地了解它是如何工作的,您可以删除 group by 和 sum() 并在聚合之前查看数字。按 empname 排序,val 将有助于查看 [count] 的值如何根据每个员工的不同 val 而变化。
注意:我已尽我最大的努力以我目前的英语水平。如果您需要一个(或两个,或任意数量),请随时要求澄清。