使用行和列的组合进行聚合

时间:2013-06-07 06:58:22

标签: sql-server sql-server-2008

范围的样本数据表名为范围如下所示:

+-----------------+-------------------+----------+----------+
| SectionCategory |     RangeName     | LowerEnd | UpperEnd |
+-----------------+-------------------+----------+----------+
| Sanction        | 0-7 days          |        0 |        7 |
| Sanction        | 8-15 days         |        8 |       15 |
| Sanction        | More than 15 days |       16 |    99999 |
| Disbursal       | 0-7 days          |        0 |        7 |
| Disbursal       | 8-15 days         |        8 |       15 |
| Disbursal       | More than 15 days |       16 |    99999 |
+-----------------+-------------------+----------+----------+

来自延迟表的样本数据如下所示:

+-----------+---------------+-----------------+
| Loan No.  | SanctionDelay | Disbursal Delay |
+-----------+---------------+-----------------+
|       247 |             8 |              35 |
|       661 |            18 |              37 |
|      1235 |            12 |               6 |
|      1235 |             8 |              15 |
|      1241 |            28 |               9 |
|      1241 |            11 |               9 |
|      1283 |            22 |              20 |
|      1283 |            28 |              41 |
|      1523 |             1 |              27 |
|      1523 |             6 |              28 |
+-----------+---------------+-----------------+

所需的输出如下所示:

+-----------+-------------------+-------+
|  Section  |       Range       | Count |
+-----------+-------------------+-------+
| Sanction  | 0-7 days          |     2 |
| Sanction  | 8-15 days         |     4 |
| Sanction  | More than 15 days |     4 |
| Disbursal | 0-7 days          |     1 |
| Disbursal | 8-15 days         |     3 |
| Disbursal | More than 15 days |     6 |
+-----------+-------------------+-------+

目前编写了两个单独的查询,UNION用于整理输出。

从可维护性的角度来看,是否可以在单个查询中执行此操作? (对于Ranges表中的制裁,应使用Delays Table中的SanctionDelay列,对于Disbursal,应使用DisbursalDelay列。)需要的是因为贷款生命周期的阶段数预计会增加,并且越来越多的UNIONs需要整理输出。

2 个答案:

答案 0 :(得分:3)

可以使用CROSS JOIN来完成,但不确定效率如何。

示例数据:

declare @Ranges table (SectionCategory varchar(10) not null,RangeName varchar(20) not null,LowerEnd int not null,UpperEnd int not null)
insert into @Ranges (SectionCategory,RangeName,LowerEnd,UpperEnd) values
('Sanction','0-7 days',0,7),
('Sanction','8-15 days',8,15),
('Sanction','More than 15 days',16,99999),
('Disbursal','0-7 days',0,7),
('Disbursal','8-15 days',8,15),
('Disbursal','More than 15 days',16,99999)

declare @Delays table (LoanNo int not null,SanctionDelay int not null,DisbursalDelay int not null)
insert into @Delays (LoanNo,SanctionDelay,DisbursalDelay) values
( 247, 8,35),
( 661,18,37),
(1235,12, 6),
(1235, 8,15),
(1241,28, 9),
(1241,11, 9),
(1283,22,20),
(1283,28,41),
(1523, 1,27),
(1523, 6,28)

查询(必须与样本数据在同一批次中运行):

select
    r.SectionCategory,
    r.RangeName,
    SUM(CASE
        WHEN r.SectionCategory='Sanction' and d.SanctionDelay BETWEEN r.LowerEnd and r.UpperEnd then 1
        WHEN r.SectionCategory='Disbursal' and d.DisbursalDelay BETWEEN r.LowerEnd and r.UpperEnd then 1
        else 0 end) as Cnt
from @Ranges r
    cross join
    @Delays d
group by
    r.SectionCategory,
    r.RangeName
order by SectionCategory,RangeName

结果:

SectionCategory RangeName            Cnt
--------------- -------------------- -----------
Disbursal       0-7 days             1
Disbursal       8-15 days            3
Disbursal       More than 15 days    6
Sanction        0-7 days             2
Sanction        8-15 days            4
Sanction        More than 15 days    4

从可维护性的角度来看,在延迟表中添加一个延迟列并指定延迟类型的附加列可能更好。目前,感觉就像某种形式的属性拆分 - 在Ranges表中,类型表示为列值(SanctionDisbursal等),但在延迟表中,这同样“type”在表元数据中以不同的列名称表示。

你说“贷款生命周期的阶段数预计会增加”,我希望这种交叉(代表某些表中的数据属性和其他表中的元数据)将增加痛苦写得体面的查询。

答案 1 :(得分:2)

试试这个

SELECT 
  SectionCategory
 ,RangeName
 ,CASE 
  WHEN R.SectionCategory='Sanction' THEN
   (SELECT COUNT(1) FROM Delays D WHERE D.Sanction_Delay BETWEEN R.LowerEnd AND R.UpperEnd) 
  WHEN R.SectionCategory='Disbursal' THEN
   (SELECT COUNT(1) FROM Delays D WHERE D.[Disbursal Delay] BETWEEN R.LowerEnd AND R.UpperEnd) 
END as cnt
FROM Ranges R

这是 SQLFiddle 演示