如何根据条件聚合数据
how to aggregate data based on condition
我想通过比较 SQL 中的创建日期和发布日期来计算每个项目的未清数量,如果发布日期小于同一项目其他行的创建日期,则应将数量添加到开放数量
例如,第 3 行的未清数量为 3,因为项目 a 创建于 2021 年 1 月 11 日,当时只有发布日期为 2021 年 2 月 12 日的第 2 行仍然未清。
第 1 行未添加到第 3 行的未清数量,因为它已于 2021 年 1 月 10 日发出。
对于项目 b 的第 6 行,第 4 行和第 5 行未在第 6 行的创建日期 (14.02.2021) 发布,因此未结数量为 2+3(第 4 行数量+第 5 行数量)。
我知道这是不正确的,但如果可能的话,我会添加如下代码。
select item, createdate, issuedate, qty
sum(qty) OVER(PARTITION BY item where createdate_issuedate_aggrow < createdate_referencerow < issuedate_aggrow ) from t
item
creation date
issue date
qty
open quantity
a
05.01.2021
10.01.2021
2
0
a
07.01.2021
12.02.2021
3
2
a
11.01.2021
12.02.2021
4
3
b
05.01.2021
10.05.2021
2
0
b
11.01.2021
12.05.2021
3
2
b
14.02.2021
15.02.2021
4
2+3 = 5
以下解决方案仅适用于 Oracle 数据库。
希望对HANA有所启发。
您的示例数据
create table Sample_Data (item, creation_date, issue_date, qty) as (
select 'a', to_date('05.01.2021', 'DD.MM.YYYY'), to_date('10.01.2021', 'DD.MM.YYYY'), 2 from dual union all
select 'a', to_date('07.01.2021', 'DD.MM.YYYY'), to_date('12.02.2021', 'DD.MM.YYYY'), 3 from dual union all
select 'a', to_date('11.01.2021', 'DD.MM.YYYY'), to_date('12.02.2021', 'DD.MM.YYYY'), 4 from dual union all
select 'b', to_date('05.01.2021', 'DD.MM.YYYY'), to_date('10.05.2021', 'DD.MM.YYYY'), 2 from dual union all
select 'b', to_date('11.01.2021', 'DD.MM.YYYY'), to_date('12.05.2021', 'DD.MM.YYYY'), 3 from dual union all
select 'b', to_date('14.02.2021', 'DD.MM.YYYY'), to_date('15.02.2021', 'DD.MM.YYYY'), 4 from dual
)
;
- 首先,在 row_numbered_tab 视图中,我对每个项目的所有行进行了编号(row_number 函数) ,我计算每一行的所有前行
- 其次,对于每一行,我生成的行数与它的行数一样多prev_count_rows
- 然后,我可以通过视图 t 和 tt
来实现你的逻辑
With row_numbered_tab (ITEM, CREATION_DATE, ISSUE_DATE, QTY, prev_count_rows, rnb) as (
select ITEM, CREATION_DATE, ISSUE_DATE, QTY
, count(ISSUE_DATE)over(partition by ITEM order by CREATION_DATE, ISSUE_DATE ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) prev_count_rows
, row_number()over(partition by ITEM order by CREATION_DATE, ISSUE_DATE) rnb
from Sample_Data t
)
, cte(ITEM, CREATION_DATE, ISSUE_DATE, QTY, prev_count_rows, rnb, RUNNING_REF_CREATION_DATE) as (
select ITEM, CREATION_DATE, ISSUE_DATE, QTY, prev_count_rows, rnb, CREATION_DATE RUNNING_REF_CREATION_DATE
from row_numbered_tab t
union all
select t.ITEM, t.CREATION_DATE, t.ISSUE_DATE, t.QTY, c.prev_count_rows, c.rnb - 1 rnb
, case when t.ITEM = c.ITEM and t.rnb = c.rnb - 1 then c.RUNNING_REF_CREATION_DATE else t.CREATION_DATE end
from row_numbered_tab t
join cte c
on t.rnb = c.rnb - 1
and t.ITEM = c.ITEM
)
select ITEM, CREATION_DATE, ISSUE_DATE, QTY, O_QTY as Open_Quantity
from (
select t.*, max(O_QTY)over(partition by ITEM, prev_count_rows)mx
from (
select ITEM, CREATION_DATE, ISSUE_DATE, QTY, prev_count_rows, RNB, RUNNING_REF_CREATION_DATE
, NVL(
sum(case when RUNNING_REF_CREATION_DATE < ISSUE_DATE then QTY else null end)
over(
partition by ITEM, prev_count_rows order by CREATION_DATE, ISSUE_DATE
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
)
, 0
)O_QTY
from cte
) t
)tt
where O_QTY = MX
order by ITEM, CREATION_DATE
;
这是一个反复出现的模式。如果要将 table 与自身进行比较并构建条件聚合,则需要将 self-join 与聚合结合使用。这不仅适用于 SAP HANA,而且适用于一般 SQL 模式。
从这个角度来看,您的问题与那个问题非常相似:
How do i use STRING_AGG in combination with WHERE clause?
以下语句将为您提供所需的结果,并且在任何数据库系统上都可以类似地工作。
示例数据
create table sample_Data (item, creation_date, issue_date, qty) as (
select 'a', to_date('05.01.2021', 'DD.MM.YYYY'), to_date('10.01.2021', 'DD.MM.YYYY'), 2 from dummy union all
select 'a', to_date('07.01.2021', 'DD.MM.YYYY'), to_date('12.02.2021', 'DD.MM.YYYY'), 3 from dummy union all
select 'a', to_date('11.01.2021', 'DD.MM.YYYY'), to_date('12.02.2021', 'DD.MM.YYYY'), 4 from dummy union all
select 'b', to_date('05.01.2021', 'DD.MM.YYYY'), to_date('10.05.2021', 'DD.MM.YYYY'), 2 from dummy union all
select 'b', to_date('11.01.2021', 'DD.MM.YYYY'), to_date('12.05.2021', 'DD.MM.YYYY'), 3 from dummy union all
select 'b', to_date('14.02.2021', 'DD.MM.YYYY'), to_date('15.02.2021', 'DD.MM.YYYY'), 4 from dummy
)
;
查询
SELECT new_record.*, ifnull(sum(open_record.qty),0) AS open_quantity
FROM sample_data new_record
LEFT JOIN sample_data open_record
ON new_record.item = open_record.item
AND open_record.issue_date > new_record.creation_date
AND open_record.creation_date < new_record.creation_date
GROUP BY new_record.item, new_record.creation_date, new_record.issue_date, new_record.qty
ORDER BY new_record.item, new_record.creation_date, new_record.issue_date
结果
我想通过比较 SQL 中的创建日期和发布日期来计算每个项目的未清数量,如果发布日期小于同一项目其他行的创建日期,则应将数量添加到开放数量
例如,第 3 行的未清数量为 3,因为项目 a 创建于 2021 年 1 月 11 日,当时只有发布日期为 2021 年 2 月 12 日的第 2 行仍然未清。
第 1 行未添加到第 3 行的未清数量,因为它已于 2021 年 1 月 10 日发出。
对于项目 b 的第 6 行,第 4 行和第 5 行未在第 6 行的创建日期 (14.02.2021) 发布,因此未结数量为 2+3(第 4 行数量+第 5 行数量)。
我知道这是不正确的,但如果可能的话,我会添加如下代码。
select item, createdate, issuedate, qty
sum(qty) OVER(PARTITION BY item where createdate_issuedate_aggrow < createdate_referencerow < issuedate_aggrow ) from t
item | creation date | issue date | qty | open quantity |
---|---|---|---|---|
a | 05.01.2021 | 10.01.2021 | 2 | 0 |
a | 07.01.2021 | 12.02.2021 | 3 | 2 |
a | 11.01.2021 | 12.02.2021 | 4 | 3 |
b | 05.01.2021 | 10.05.2021 | 2 | 0 |
b | 11.01.2021 | 12.05.2021 | 3 | 2 |
b | 14.02.2021 | 15.02.2021 | 4 | 2+3 = 5 |
以下解决方案仅适用于 Oracle 数据库。 希望对HANA有所启发。
您的示例数据
create table Sample_Data (item, creation_date, issue_date, qty) as (
select 'a', to_date('05.01.2021', 'DD.MM.YYYY'), to_date('10.01.2021', 'DD.MM.YYYY'), 2 from dual union all
select 'a', to_date('07.01.2021', 'DD.MM.YYYY'), to_date('12.02.2021', 'DD.MM.YYYY'), 3 from dual union all
select 'a', to_date('11.01.2021', 'DD.MM.YYYY'), to_date('12.02.2021', 'DD.MM.YYYY'), 4 from dual union all
select 'b', to_date('05.01.2021', 'DD.MM.YYYY'), to_date('10.05.2021', 'DD.MM.YYYY'), 2 from dual union all
select 'b', to_date('11.01.2021', 'DD.MM.YYYY'), to_date('12.05.2021', 'DD.MM.YYYY'), 3 from dual union all
select 'b', to_date('14.02.2021', 'DD.MM.YYYY'), to_date('15.02.2021', 'DD.MM.YYYY'), 4 from dual
)
;
- 首先,在 row_numbered_tab 视图中,我对每个项目的所有行进行了编号(row_number 函数) ,我计算每一行的所有前行
- 其次,对于每一行,我生成的行数与它的行数一样多prev_count_rows
- 然后,我可以通过视图 t 和 tt 来实现你的逻辑
With row_numbered_tab (ITEM, CREATION_DATE, ISSUE_DATE, QTY, prev_count_rows, rnb) as (
select ITEM, CREATION_DATE, ISSUE_DATE, QTY
, count(ISSUE_DATE)over(partition by ITEM order by CREATION_DATE, ISSUE_DATE ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) prev_count_rows
, row_number()over(partition by ITEM order by CREATION_DATE, ISSUE_DATE) rnb
from Sample_Data t
)
, cte(ITEM, CREATION_DATE, ISSUE_DATE, QTY, prev_count_rows, rnb, RUNNING_REF_CREATION_DATE) as (
select ITEM, CREATION_DATE, ISSUE_DATE, QTY, prev_count_rows, rnb, CREATION_DATE RUNNING_REF_CREATION_DATE
from row_numbered_tab t
union all
select t.ITEM, t.CREATION_DATE, t.ISSUE_DATE, t.QTY, c.prev_count_rows, c.rnb - 1 rnb
, case when t.ITEM = c.ITEM and t.rnb = c.rnb - 1 then c.RUNNING_REF_CREATION_DATE else t.CREATION_DATE end
from row_numbered_tab t
join cte c
on t.rnb = c.rnb - 1
and t.ITEM = c.ITEM
)
select ITEM, CREATION_DATE, ISSUE_DATE, QTY, O_QTY as Open_Quantity
from (
select t.*, max(O_QTY)over(partition by ITEM, prev_count_rows)mx
from (
select ITEM, CREATION_DATE, ISSUE_DATE, QTY, prev_count_rows, RNB, RUNNING_REF_CREATION_DATE
, NVL(
sum(case when RUNNING_REF_CREATION_DATE < ISSUE_DATE then QTY else null end)
over(
partition by ITEM, prev_count_rows order by CREATION_DATE, ISSUE_DATE
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
)
, 0
)O_QTY
from cte
) t
)tt
where O_QTY = MX
order by ITEM, CREATION_DATE
;
这是一个反复出现的模式。如果要将 table 与自身进行比较并构建条件聚合,则需要将 self-join 与聚合结合使用。这不仅适用于 SAP HANA,而且适用于一般 SQL 模式。
从这个角度来看,您的问题与那个问题非常相似: How do i use STRING_AGG in combination with WHERE clause?
以下语句将为您提供所需的结果,并且在任何数据库系统上都可以类似地工作。
示例数据
create table sample_Data (item, creation_date, issue_date, qty) as (
select 'a', to_date('05.01.2021', 'DD.MM.YYYY'), to_date('10.01.2021', 'DD.MM.YYYY'), 2 from dummy union all
select 'a', to_date('07.01.2021', 'DD.MM.YYYY'), to_date('12.02.2021', 'DD.MM.YYYY'), 3 from dummy union all
select 'a', to_date('11.01.2021', 'DD.MM.YYYY'), to_date('12.02.2021', 'DD.MM.YYYY'), 4 from dummy union all
select 'b', to_date('05.01.2021', 'DD.MM.YYYY'), to_date('10.05.2021', 'DD.MM.YYYY'), 2 from dummy union all
select 'b', to_date('11.01.2021', 'DD.MM.YYYY'), to_date('12.05.2021', 'DD.MM.YYYY'), 3 from dummy union all
select 'b', to_date('14.02.2021', 'DD.MM.YYYY'), to_date('15.02.2021', 'DD.MM.YYYY'), 4 from dummy
)
;
查询
SELECT new_record.*, ifnull(sum(open_record.qty),0) AS open_quantity
FROM sample_data new_record
LEFT JOIN sample_data open_record
ON new_record.item = open_record.item
AND open_record.issue_date > new_record.creation_date
AND open_record.creation_date < new_record.creation_date
GROUP BY new_record.item, new_record.creation_date, new_record.issue_date, new_record.qty
ORDER BY new_record.item, new_record.creation_date, new_record.issue_date
结果