Teradata SQL:创建 volatile table,根据逻辑自动填充多行
Teradata SQL: Create volatile table with multiple rows automatically populated based on logic
我创建了一个脚本,它创建了一个具有 3 列的可变 table,并插入了 5 行:
create multiset volatile table dr (
period int
, st_date date
, end_date date
)
primary index (period) on commit preserve rows;
insert into dr (period,st_date,end_date)
select *
from( select *
from (select '201712' period
, '2017-10-01' st_date
, '2017-12-31' end_date
)t1
union all
select *
from (select '201612' period
, '2016-10-01' st_date
, '2016-12-31' end_date
)t2
union all
select *
from (select '201512' period
, '2015-10-01' st_date
, '2015-12-31' end_date
)t3
union all
select *
from (select '201412' period
, '2014-10-01' st_date
, '2014-12-31' end_date
)t4
union all
select *
from (select '201312' period
, '2013-10-01' st_date
, '2013-12-31' end_date
)t5
)t
我将把这个 table 加入其他几个 table 的日期范围。
这里我是手动为每一个插入的行输入信息,这有点麻烦而且效率低下。
是否有更自动化的方法来执行此操作,并在一个日期(例如 2017 年 12 月 31 日)完成所有操作 运行?我可以自己制定逻辑,但不确定如何构造插入语句以允许这种逻辑。
谢谢!
编辑
我希望能够在任何连续 3 个月的时间段内自动执行此操作,即使跨年(例如 2017-11-01 到 2018-01-31,或 2017-12-01 到 2018-02-28),然后继续连续 3 个月倒退 5 年。
您可以使用 sys_calendar.calendar
table 推导这些周期,使用一些 window 函数变得有点狡猾:
SELECT distinct
year_of_calendar * 100 + max(month_of_year) OVER (PARTITION BY year_of_calendar) as "period",
min(calendar_date) OVER (PARTITION BY year_of_calendar) as st_date,
max(calendar_date) OVER (PARTITION BY year_of_calendar) as end_date
FROM sys_calendar.calendar
WHERE month_of_year BETWEEN 10 AND 12
AND year_of_calendar BETWEEN 2013 AND 2017
+--------+------------+------------+
| period | st_date | end_date |
+--------+------------+------------+
| 201312 | 2013-10-01 | 2013-12-31 |
| 201412 | 2014-10-01 | 2014-12-31 |
| 201512 | 2015-10-01 | 2015-12-31 |
| 201612 | 2016-10-01 | 2016-12-31 |
| 201712 | 2017-10-01 | 2017-12-31 |
+--------+------------+------------+
将其包装到 CREATE TABLE 语句中:
CREATE MULTISET VOLATILE TABLE dr AS
(
SELECT distinct
year_of_calendar * 100 + max(month_of_year) OVER (PARTITION BY year_of_calendar) as "period",
min(calendar_date) OVER (PARTITION BY year_of_calendar) as st_date,
max(calendar_date) OVER (PARTITION BY year_of_calendar) as end_date
FROM sys_calendar.calendar
WHERE month_of_year BETWEEN 10 AND 12
AND year_of_calendar BETWEEN 2013 AND 2017
)
WITH DATA
PRIMARY INDEX ("period")
ON COMMIT PRESERVE ROWS;
我建议在宏中使用一些基于 TRUNC/ADD_MONTHS/LAST_DAY 的逻辑:
REPLACE MACRO testmac (in_date DATE)
AS
(
CREATE SET VOLATILE TABLE dr -- no need for MULTISET
AS
(
SELECT year_of_calendar * 100 + month_of_year AS PERIOD,
Add_Months(calendar_date,-2) AS st_date,
Last_Day(calendar_date) AS end_date
FROM sys_calendar.CALENDAR
WHERE year_of_calendar -- current_month and two previous months
BETWEEN Extract(YEAR From Add_Months(:in_date,-48))
AND Extract(YEAR From :in_date)
AND month_of_year = Extract(MONTH From :in_date)
AND day_of_month = 1 -- only one row per year
) WITH DATA
UNIQUE PRIMARY INDEX (PERIOD)
ON COMMIT PRESERVE ROWS;
);
EXEC testmac(DATE '2018-01-22');
您还可以应用递归查询或 EXPAND ON。
编辑:
EXPAND ON 很好而且很短:-)
SELECT Extract(YEAR From End(pd)) * 100 + Extract(MONTH From End(pd)) AS PERIOD
,Trunc(Add_Months(End(pd),-2), 'mon') AS st_date
,Last_Day(End(pd)) AS end_date
FROM sys_calendar.CALENDAR -- specify the date once
WHERE calendar_date = DATE '2018-01-22' -- or :in_date in the macro
EXPAND ON PERIOD(Add_Months(calendar_date,-60), calendar_date) AS pd
BY INTERVAL '1' YEAR -- one row per year
我创建了一个脚本,它创建了一个具有 3 列的可变 table,并插入了 5 行:
create multiset volatile table dr (
period int
, st_date date
, end_date date
)
primary index (period) on commit preserve rows;
insert into dr (period,st_date,end_date)
select *
from( select *
from (select '201712' period
, '2017-10-01' st_date
, '2017-12-31' end_date
)t1
union all
select *
from (select '201612' period
, '2016-10-01' st_date
, '2016-12-31' end_date
)t2
union all
select *
from (select '201512' period
, '2015-10-01' st_date
, '2015-12-31' end_date
)t3
union all
select *
from (select '201412' period
, '2014-10-01' st_date
, '2014-12-31' end_date
)t4
union all
select *
from (select '201312' period
, '2013-10-01' st_date
, '2013-12-31' end_date
)t5
)t
我将把这个 table 加入其他几个 table 的日期范围。
这里我是手动为每一个插入的行输入信息,这有点麻烦而且效率低下。
是否有更自动化的方法来执行此操作,并在一个日期(例如 2017 年 12 月 31 日)完成所有操作 运行?我可以自己制定逻辑,但不确定如何构造插入语句以允许这种逻辑。
谢谢!
编辑 我希望能够在任何连续 3 个月的时间段内自动执行此操作,即使跨年(例如 2017-11-01 到 2018-01-31,或 2017-12-01 到 2018-02-28),然后继续连续 3 个月倒退 5 年。
您可以使用 sys_calendar.calendar
table 推导这些周期,使用一些 window 函数变得有点狡猾:
SELECT distinct
year_of_calendar * 100 + max(month_of_year) OVER (PARTITION BY year_of_calendar) as "period",
min(calendar_date) OVER (PARTITION BY year_of_calendar) as st_date,
max(calendar_date) OVER (PARTITION BY year_of_calendar) as end_date
FROM sys_calendar.calendar
WHERE month_of_year BETWEEN 10 AND 12
AND year_of_calendar BETWEEN 2013 AND 2017
+--------+------------+------------+
| period | st_date | end_date |
+--------+------------+------------+
| 201312 | 2013-10-01 | 2013-12-31 |
| 201412 | 2014-10-01 | 2014-12-31 |
| 201512 | 2015-10-01 | 2015-12-31 |
| 201612 | 2016-10-01 | 2016-12-31 |
| 201712 | 2017-10-01 | 2017-12-31 |
+--------+------------+------------+
将其包装到 CREATE TABLE 语句中:
CREATE MULTISET VOLATILE TABLE dr AS
(
SELECT distinct
year_of_calendar * 100 + max(month_of_year) OVER (PARTITION BY year_of_calendar) as "period",
min(calendar_date) OVER (PARTITION BY year_of_calendar) as st_date,
max(calendar_date) OVER (PARTITION BY year_of_calendar) as end_date
FROM sys_calendar.calendar
WHERE month_of_year BETWEEN 10 AND 12
AND year_of_calendar BETWEEN 2013 AND 2017
)
WITH DATA
PRIMARY INDEX ("period")
ON COMMIT PRESERVE ROWS;
我建议在宏中使用一些基于 TRUNC/ADD_MONTHS/LAST_DAY 的逻辑:
REPLACE MACRO testmac (in_date DATE)
AS
(
CREATE SET VOLATILE TABLE dr -- no need for MULTISET
AS
(
SELECT year_of_calendar * 100 + month_of_year AS PERIOD,
Add_Months(calendar_date,-2) AS st_date,
Last_Day(calendar_date) AS end_date
FROM sys_calendar.CALENDAR
WHERE year_of_calendar -- current_month and two previous months
BETWEEN Extract(YEAR From Add_Months(:in_date,-48))
AND Extract(YEAR From :in_date)
AND month_of_year = Extract(MONTH From :in_date)
AND day_of_month = 1 -- only one row per year
) WITH DATA
UNIQUE PRIMARY INDEX (PERIOD)
ON COMMIT PRESERVE ROWS;
);
EXEC testmac(DATE '2018-01-22');
您还可以应用递归查询或 EXPAND ON。
编辑:
EXPAND ON 很好而且很短:-)
SELECT Extract(YEAR From End(pd)) * 100 + Extract(MONTH From End(pd)) AS PERIOD
,Trunc(Add_Months(End(pd),-2), 'mon') AS st_date
,Last_Day(End(pd)) AS end_date
FROM sys_calendar.CALENDAR -- specify the date once
WHERE calendar_date = DATE '2018-01-22' -- or :in_date in the macro
EXPAND ON PERIOD(Add_Months(calendar_date,-60), calendar_date) AS pd
BY INTERVAL '1' YEAR -- one row per year