问题描述
我对 sql 还很陌生,似乎无法让我的查询执行我想要的操作。
我想要基于另一个条件发生的一列的总和。
我的桌子看起来像这样:
ID | 位置 | Scan_Code | 扫描日期 |
---|---|---|---|
1 | 地点A | 01 | 2021-02-01 |
1 | 地点A | 02 | 2021-02-01 |
2 | 地点A | 01 | 2021-02-01 |
2 | 地点A | 02 | 2021-02-02 |
3 | PlaceB | 01 | 2021-02-01 |
3 | PlaceB | 02 | 2021-02-01 |
3 | PlaceB | 01 | 2021-02-02 |
3 | PlaceB | 02 | 2021-02-02 |
4 | PlaceB | 02 | 2021-02-02 |
结果应该将每个位置的任何给定日期的 Scan 01 的发生次数与 Scan 02 的总和相加,如果该 ID 在同一天发生了 Scan 01。
上表的预期结果
|Scan_Date |Location|Sum_Scan01|ConditionalSum02|
|----------|--------|----------|----------------|
|2021-02-01|PlaceA |2 |1 |
|2021-02-01|PlaceB |1 |1 |
|2021-02-02|PlaceB |1 |1 |
我的查询目前看起来像这样,无论扫描 01 是否发生,我都会对扫描 02 的所有内容求和,但我无法弄清楚如何包含该条件,因为我不能在第二种情况下重复第一个:
select
scan_date,Location,SUM(case when scan_code EQ '01' then 1 else 0 end) as Scan01,SUM(case when scan_code EQ '02' then 1 else 0 end) as Scan02
from ScanDB
where scan_date between '?From' and '?To'
group by scan_date,Location
非常感谢新用户。
解决方法
您可能需要嵌套聚合,这应该可以:
with cte as
( select
id,-- include id in inital calculation
scan_date,Location,SUM(case when scan_code = '01' then 1 else 0 end) as cntScan01,SUM(case when scan_code = '02' then 1 else 0 end) as cntScan02
from ScanDB
where scan_date between '?From' and '?To'
group by id,scan_date,Location
)
select
scan_date,SUM(cntScan01) as Scan01,-- check if 01 exists for same id
SUM(case when cntScan01 > 0 then cntScan02 else 0 end) as Scan02
from cte
group by scan_date,Location
,
我倾向于使用窗口函数:
select scan_date,sum(case when scan_code EQ '01' then 1 else 0 end) as Scan01,sum(case when num_id_01 > 0 and scan_code EQ '02' then 1 else 0 end) as Scan02
from (select s.*,sum(case when scan_code EQ '01' then 1 else 0 end) over (partition by id,scan_date) as num_id_01
from ScanDB s
where s.scan_date between '?From' and '?To'
) s
group by scan_date,Location;