在 DB2 SQL 中使用 Stored Procedures/Macros 声明和循环
Declare and Loop using Stored Procedures/Macros in DB2 SQL
我有一个 table_A,其名称和交货日期如下
Name
Del_dt
Mark
2022-04-01
Mark
2022-04-03
Mark
2022-04-05
Mark
2022-04-07
Mark
2022-04-09
Dave
2022-04-02
Dave
2022-04-04
Dave
2022-04-06
Dave
2022-04-08
Dave
2022-04-10
等等。我想要一个特定日期的 Name 的累计计数。例如日期从 2022-04-07 到 2022-04-10
的输出样本
Date
Name
cul_cnt
2022-04-07
Mark
4
2022-04-08
Mark
4
2022-04-09
Mark
5
2022-04-10
Mark
5
2022-04-07
Dave
3
2022-04-08
Dave
4
2022-04-09
Dave
4
2022-04-10
Dave
5
当然,不同名称的日期可以相同。我正在尝试使用 Dynamic SQL(因为我是初学者,想探索更多)。我根据我能找到的有关 Dynamic SQL 方法的内容生成了以下代码。我也对其他方法持开放态度。
begin
declare cur_date date;
declare og_date date;
declare Cust_Name varchar2(4);
declare cul_cnt number;
set cur_date = current_date; /*today's date*/
set og_date = cur_date - 10; /*calculating cumulative counts for last 10 days*/
loop
select Name,count(Name) into Cust_Name,cul_cnt,og_date
from table_A
where prod_type like 'SHOES' /*Another column in the table just for filter*/
and Del_dt <= og_date
group by Name;
og_date = og_date + 1;
exit when (og_date > cur_date);
end;
end;
目前我遇到这个错误
Error report -
Error starting at line : 1 in command -
DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=CUR_DATE;SECTION, DRIVER=3.69.49
不过,我敢肯定代码中会有更多错误。如何获得所需的输出,如输出 table 所示。另外,我如何获得 og_date(输出中的日期列),因为它不存在于原始 table_A 中,而是定义的变量
试试这个:
WITH
-- Table of 10 dates generation starting from 2022-04-10
-- CURRENT_DATE can be used instead
D (I, DT) AS
(
SELECT 1, DATE ('2022-04-10') FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT I + 1, DT - 1 DAY FROM D WHERE I < 10
)
/*
, table_A (Name, Del_dt) AS
(
SELECT 'Mark', DATE ('2022-04-01') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Mark', DATE ('2022-04-03') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Mark', DATE ('2022-04-05') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Mark', DATE ('2022-04-07') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Mark', DATE ('2022-04-09') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-02') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-04') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-06') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-08') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-10') FROM SYSIBM.SYSDUMMY1
)
*/
SELECT D.DT, A.Name, A.cul_cnt
FROM D
CROSS JOIN TABLE
(
SELECT A.Name, COUNT (1) cul_cnt
FROM table_A A
WHERE A.Del_dt <= D.DT
GROUP BY A.Name
) A
WHERE DT BETWEEN DATE ('2022-04-07') AND DATE ('2022-04-10')
ORDER BY A.Name DESC, D.DT
如果您取消对注释掉的块的注释,您可以 运行 语句原样。本例中的结果与您的结果相同:
DT
NAME
CUL_CNT
2022-04-07
Mark
4
2022-04-08
Mark
4
2022-04-09
Mark
5
2022-04-10
Mark
5
2022-04-07
Dave
3
2022-04-08
Dave
4
2022-04-09
Dave
4
2022-04-10
Dave
5
Oracle 中的相同查询:
WITH
D (I, DT) AS
(
SELECT 1, TO_DATE ('2022-04-10', 'YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT I + 1, DT - INTERVAL '1' DAY FROM D WHERE I < 10
)
/*
, table_A (Name, Del_dt) AS
(
SELECT 'Mark', TO_DATE ('2022-04-01', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Mark', TO_DATE ('2022-04-03', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Mark', TO_DATE ('2022-04-05', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Mark', TO_DATE ('2022-04-07', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Mark', TO_DATE ('2022-04-09', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-02', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-04', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-06', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-08', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-10', 'YYYY-MM-DD') FROM DUAL
)
*/
SELECT TO_CHAR (D.DT, 'YYYY-MM-DD') DT, A.Name, A.cul_cnt
FROM D
CROSS JOIN LATERAL
(
SELECT A.Name, COUNT (1) cul_cnt
FROM table_A A
WHERE A.Del_dt <= D.DT
GROUP BY A.Name
) A
WHERE D.DT BETWEEN TO_DATE ('2022-04-07', 'YYYY-MM-DD') AND TO_DATE ('2022-04-10', 'YYYY-MM-DD')
ORDER BY A.Name DESC, D.DT
我有一个 table_A,其名称和交货日期如下
Name | Del_dt |
---|---|
Mark | 2022-04-01 |
Mark | 2022-04-03 |
Mark | 2022-04-05 |
Mark | 2022-04-07 |
Mark | 2022-04-09 |
Dave | 2022-04-02 |
Dave | 2022-04-04 |
Dave | 2022-04-06 |
Dave | 2022-04-08 |
Dave | 2022-04-10 |
等等。我想要一个特定日期的 Name 的累计计数。例如日期从 2022-04-07 到 2022-04-10
的输出样本Date | Name | cul_cnt |
---|---|---|
2022-04-07 | Mark | 4 |
2022-04-08 | Mark | 4 |
2022-04-09 | Mark | 5 |
2022-04-10 | Mark | 5 |
2022-04-07 | Dave | 3 |
2022-04-08 | Dave | 4 |
2022-04-09 | Dave | 4 |
2022-04-10 | Dave | 5 |
当然,不同名称的日期可以相同。我正在尝试使用 Dynamic SQL(因为我是初学者,想探索更多)。我根据我能找到的有关 Dynamic SQL 方法的内容生成了以下代码。我也对其他方法持开放态度。
begin
declare cur_date date;
declare og_date date;
declare Cust_Name varchar2(4);
declare cul_cnt number;
set cur_date = current_date; /*today's date*/
set og_date = cur_date - 10; /*calculating cumulative counts for last 10 days*/
loop
select Name,count(Name) into Cust_Name,cul_cnt,og_date
from table_A
where prod_type like 'SHOES' /*Another column in the table just for filter*/
and Del_dt <= og_date
group by Name;
og_date = og_date + 1;
exit when (og_date > cur_date);
end;
end;
目前我遇到这个错误
Error report -
Error starting at line : 1 in command -
DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=CUR_DATE;SECTION, DRIVER=3.69.49
不过,我敢肯定代码中会有更多错误。如何获得所需的输出,如输出 table 所示。另外,我如何获得 og_date(输出中的日期列),因为它不存在于原始 table_A 中,而是定义的变量
试试这个:
WITH
-- Table of 10 dates generation starting from 2022-04-10
-- CURRENT_DATE can be used instead
D (I, DT) AS
(
SELECT 1, DATE ('2022-04-10') FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT I + 1, DT - 1 DAY FROM D WHERE I < 10
)
/*
, table_A (Name, Del_dt) AS
(
SELECT 'Mark', DATE ('2022-04-01') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Mark', DATE ('2022-04-03') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Mark', DATE ('2022-04-05') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Mark', DATE ('2022-04-07') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Mark', DATE ('2022-04-09') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-02') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-04') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-06') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-08') FROM SYSIBM.SYSDUMMY1
UNION ALL SELECT 'Dave', DATE ('2022-04-10') FROM SYSIBM.SYSDUMMY1
)
*/
SELECT D.DT, A.Name, A.cul_cnt
FROM D
CROSS JOIN TABLE
(
SELECT A.Name, COUNT (1) cul_cnt
FROM table_A A
WHERE A.Del_dt <= D.DT
GROUP BY A.Name
) A
WHERE DT BETWEEN DATE ('2022-04-07') AND DATE ('2022-04-10')
ORDER BY A.Name DESC, D.DT
如果您取消对注释掉的块的注释,您可以 运行 语句原样。本例中的结果与您的结果相同:
DT | NAME | CUL_CNT |
---|---|---|
2022-04-07 | Mark | 4 |
2022-04-08 | Mark | 4 |
2022-04-09 | Mark | 5 |
2022-04-10 | Mark | 5 |
2022-04-07 | Dave | 3 |
2022-04-08 | Dave | 4 |
2022-04-09 | Dave | 4 |
2022-04-10 | Dave | 5 |
Oracle 中的相同查询:
WITH
D (I, DT) AS
(
SELECT 1, TO_DATE ('2022-04-10', 'YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT I + 1, DT - INTERVAL '1' DAY FROM D WHERE I < 10
)
/*
, table_A (Name, Del_dt) AS
(
SELECT 'Mark', TO_DATE ('2022-04-01', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Mark', TO_DATE ('2022-04-03', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Mark', TO_DATE ('2022-04-05', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Mark', TO_DATE ('2022-04-07', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Mark', TO_DATE ('2022-04-09', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-02', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-04', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-06', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-08', 'YYYY-MM-DD') FROM DUAL
UNION ALL SELECT 'Dave', TO_DATE ('2022-04-10', 'YYYY-MM-DD') FROM DUAL
)
*/
SELECT TO_CHAR (D.DT, 'YYYY-MM-DD') DT, A.Name, A.cul_cnt
FROM D
CROSS JOIN LATERAL
(
SELECT A.Name, COUNT (1) cul_cnt
FROM table_A A
WHERE A.Del_dt <= D.DT
GROUP BY A.Name
) A
WHERE D.DT BETWEEN TO_DATE ('2022-04-07', 'YYYY-MM-DD') AND TO_DATE ('2022-04-10', 'YYYY-MM-DD')
ORDER BY A.Name DESC, D.DT