你可能会采用case statement获得独家范围的罪状:
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 is here。
UPDATE:在解释的尝试。
第一部分开始with
并与右括号结束称为CTE。有时它被称为inline view
,因为它可以在同一查询中多次使用,并且在某些情况下是可更新的。此处用于准备范围数据,并且适当命名为ranges
。这个名称在主查询中使用。 Val
是范围的最大值,count_all
如果范围没有上限(18+或更多,或者您希望称之为),则为1。数据行通过union all进行组合。您可以仅在括号之间复制/粘贴部分,然后运行它以查看结果。
主体加入experiences
表使用cross join范围。这会创建来自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
第一个case语句通过检查count_all产生标题 - 如果它是一个,输出more
,使用上限值else结构标题。第二种情况说明使用总和(1)进行计数。由于聚合函数忽略空值,如果未找到匹配,没有其他值的情况下计算为null,检查count_all是否为真(意味着来自经验的该行计入此范围内)就足够了,或者如果小于或等于电流范围的上限值。在上面的例子中,11不会被计入第一个范围,但会被计入所有其他范围。结果由val和count_all分组。为了更好地了解它的工作原理,您可以在汇总之前删除group by和sum()并查看数字。通过empname命令,val将帮助查看[count]的值如何根据每位员工的不同val而变化。
注意:我已经尽我所能用我目前的英语水平。如果您需要一个(或两个,或者您需要的一样多),请不要犹豫,要求澄清。
看看http://stackoverflow.com/questions/2483140/oracle-how-to-group-by-over-a-range - 它有点类似。 –
你真的想重复计算多个范围内的人吗? –