sql - TSQL to perform aggregation with Exists
问题描述
My sample data source is following
declare @t1 as table
(
sn int,
site varchar(max),
cond varchar(max),
val int
)
insert into @t1
select *
from
(values
(1, 'site1', 'X', 100),
(2, 'site1', 'Y', 200),
(3, 'site1', 'Z', 300),
(1, 'site2', 'A', 100),
(2, 'site2', 'B', 200),
(3, 'site2', 'C', 300),
(1, 'site3', 'X', 100),
(2, 'site3', 'P', 200),
(3, 'site3', 'Q', 300),
(1, 'site4', 'A', 100),
(2, 'site4', 'Y', 200),
(3, 'site4', 'Q', 300),
(1, 'site5', 'E', 100),
(1, 'site5', 'E', 1000),
(2, 'site5', 'F', 200),
(3, 'site5', 'G', 300)
) t (a, b, c, d)
I want SQL to check if there exists any row with cond=X
or cond=Y
by site and if yes, don't perform any aggregation; if no, perform a sum of val.
I am currently achieving it by following
Method1
select
ax.sn, ax.site, ax.cond,
sum(ax.revisedVal) as revisedTotal
from
(select distinct
a.sn, a.site, a.cond, a.val, t.one, m.revisedVal
from
@t1 a
outer apply
(select *
from
(select *, 1 as one
from @t1 b
where b.cond = 'Y' or b.cond = 'X') x
where a.site = x.site) t
outer apply
(values (case when t.one = 1 then null else a.val end)) m(revisedVal))ax
group by
ax.sn, ax.site, ax.cond
order by
ax.site, ax.sn
Method 2
SELECT a.sn,
a.site,
a.cond,
Sum(CASE
WHEN a.site = x.site THEN a.val
ELSE NULL
END) AS revisedVal
FROM @t1 a
OUTER apply (SELECT b.site
FROM (SELECT site
FROM @t1
WHERE cond <> 'X'
OR cond <> 'Y'
EXCEPT
SELECT site
FROM @t1
WHERE cond = 'X'
OR cond = 'Y') b
WHERE a.site = b.site) x
GROUP BY a.site,
a.sn,
a.cond
I was wondering if there is any better way of achieving this.
Edit
Desired Result
| sn | site | cond | revisedTotal |
|----|-------|------|--------------|
| 1 | site1 | X | NULL |
| 2 | site1 | Y | NULL |
| 3 | site1 | Z | NULL |
| 1 | site2 | A | 100 |
| 2 | site2 | B | 200 |
| 3 | site2 | C | 300 |
| 1 | site3 | X | NULL |
| 2 | site3 | P | NULL |
| 3 | site3 | Q | NULL |
| 1 | site4 | A | NULL |
| 2 | site4 | Y | NULL |
| 3 | site4 | Q | NULL |
| 1 | site5 | E | 1100 |
| 2 | site5 | F | 200 |
| 3 | site5 | G | 300 |
解决方案
…小提琴
select ax.sn, ax.site, ax.cond, sum(case when ax.one = 1 then null else ax.val end) as revisedTotal
from
(
select *, max(case when cond in ('Y', 'X') then 1 else 0 end) over(partition by site) as one
from @t1
) as ax
group by ax.sn, ax.site, ax.cond
order by ax.site, ax.sn;
推荐阅读
- android - 使用带有身份验证标头的 web 视图使用 REST API
- vuejs2 - 为什么在 Vue-Router 参数之后我无法访问数据?
- jmeter - 当我尝试使用 JMeter 加载 500 个用户时,由于 IP 阻塞而显示连接超时
- wpf - 按钮图像路径未在 wpf 中聚焦
- html - 使用 CSS 对图像进行 div 分割
- string - 使用 Delphi 在文本文件中查找特定字符串的行号
- php - 前端控制器中的 Typo3 插件内联记录
- authentication - React,Axios 问题:预检响应没有 HTTP ok 状态(未找到 404)
- typescript - 使用泛型将字符串转换为枚举
- equality - Isabelle 中的术语平等