分组聚合补齐结果
分组聚合补齐结果
【问题】
c# 和 SQL 按类和按日期查询出数据,
比如有表 table1 数据如下
id, type, year
1 33 2014 下半年
2 33 2014 下半年
3 33 2013 上半年
4 34 2013 上半年
要得到按 year 排序后按 type 排序,统计 year 数据,并且 year 没有的数据赋为 0,比如要得到如下结果:
year, no, type
2014 下半年 2 33
2014 上半年 0 33
2013 下半年 0 33
2013 上半年 1 33
2014 下半年 0 34
2014 上半年 0 34
2013 下半年 0 34
2013 上半年 1 34
【回答】
这种按固定序列对齐的运算,用 sql 写起来很麻烦,得用子查询拼出基准表再用 JOIN 去对齐,大概是这样:
select x._year, IFNULL(x._no,0), x._type from (
select a._year _year,b._no _no, a._type _type from (
with yt as (
select ‘2013 上半年’ _year from dual union all
select ‘2013 下半年’ _year from dual union all
select ‘2014 上半年’ _year from dual union all
select ‘2014 下半年’ _year from dual
),tt as (
select ‘33’ _type from dual union all
select ‘34’ _type from dual
) select yt._year, tt._type from yt join tt on 1 = 1
)a
left join (
select _year , count(_type) ‘_no’, ‘33’ as ‘_type’ from test5 where _type=33 group by _year
union all
select _year , count(_type) ‘_no’, ‘34’ as ‘_type’ from test5 where _type=34 group by _year
)b
on a._year = b._year and a._type = b._type) x
而用 SPL 就要简单很多,可以用循环分步算出结果来:
A | |
---|---|
1 | =connect("db") |
2 | =query("select _type,_year from test5") |
3 | =A2.id(left(_year,4)).conj([~+"上半年",~+"下半年"]) |
4 | =A2.group(_type) |
5 | =A4.news(A3;~:year,A4.~.count(year==~._year):no,A4._type:type) |
A1: 连接 db 数据库。
A2:查询原表。
A3:获取年份数字并拼出上半年、下半年的字样。id 函数从序列中获取不重复的值,left 函数是取某个字段值从左数的 n 个字符的字符串,conj 函数对含有序列作为成员的序列 A 进行和列计算,使得他们成为一个序列。这里 A2.id(left(_year,4)) 是一个序列,计算结果是序列的成员分别加“上半年”和“下半年”字符串。
A4:根据 A2 中的 _type 分组。
A5:对 A4 每组序表执行 news 函数,依据 A3 年份计算每组序表的字段值合并生成新序表。首个字段值为 ~,是相对参数 A3 的,作为年份,取名为 year;第二个字段值是由 A4 的成员也就是分组后的各个成员序表,计数而来,条件是其年份字段值与 year 字段值相同,取名为 no;第三个字段是分组类型,直接用 A4 的 _type 字段值代替就可以,取名为 type。
A2
A3
A4
A5