SAP HANA SQL - 从周日开始一周? WEEK() 默认从星期一开始
SAP HANA SQL - start week at Sunday? WEEK() starts Monday by default
业务需要一周从周日开始,但 SAP HANA SQL WEEK() 从周一开始。我如何在星期日开始日历周?我发现一些网页表明这是一个问题,例如 this one,但没有解决方案。
这里的 CALWEEK 已经在 table 中了,所以我会关注 CALWEEK_DERIVED。
创建函数:
CREATE OR REPLACE FUNCTION non_iso_week(in_date DATE)
RETURNS week INTEGER LANGUAGE SQLSCRIPT AS BEGIN
week := CASE EXTRACT(DOW FROM in_date)
WHEN 0 THEN WEEK(in_date) +1
ELSE WEEK(in_date)
END;
END;
然后:
SELECT DISTINCT
calweek
, non_iso_week(order_date) AS calweek_derived
, order_date
FROM dummy
WHERE order_date >='2020-03-07'
AND order_date <='2020-03-10'
;
以下有效。请注意,派生的 Sunday-starting 周是 CALWEEK 并且存在其他列以协助验证。
此解决方案需要存在“_SYS_BI”。“M_TIME_DIMENSION”,可能必须根据此 website.[=21] 底部的评论生成=]
我在年开始时的星期日(如 2017 年)包括特殊处理 - 查找 WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6
我将在下面进行检查:
- 今年2020
- 边缘情况 1:当一年从星期日开始时
- 边缘情况 2:当一年从星期六开始时
- 验证 SQL 从 1900 年到 2100 年检查
今年2020
-- Current year 2020 started on a Wednesday
select date_sap, YEAR(date_sap) as year_date_sap, WEEKDAY(date_sap) as weekday_date_sap, WEEK(date_sap) as SAPWEEK,
(CASE
-- subtract by 1 when year starts on a Sunday like in 2017
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) != 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap) - 1)
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) = 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap))
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap)) THEN CONCAT(YEAR(date_sap), WEEK(ADD_DAYS(date_sap, 1)) - 1)
when ((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) != 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap))
when ((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) = 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap) + 1)
when YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap)) THEN CONCAT(YEAR(date_sap), WEEK(ADD_DAYS(date_sap, 1)))
END) AS CALWEEK
from "_SYS_BI"."M_TIME_DIMENSION"
-- to eliminate missing values (appears as "?")
where date_sap >= TO_DATE('2019-12-30', 'YYYY-MM-DD')
and date_sap <= TO_DATE('2020-01-14', 'YYYY-MM-DD')
order by date_sap;
边缘情况 1:当一年从星期六开始时
2011 年
-- Same SQL but use:
where date_sap >= TO_DATE('2010-12-20', 'YYYY-MM-DD')
and date_sap <= TO_DATE('2011-01-16', 'YYYY-MM-DD')
边缘情况 2:当一年从星期日开始时
2017 年
-- Same SQL but use:
where date_sap >= TO_DATE('2016-12-20', 'YYYY-MM-DD')
and date_sap <= TO_DATE('2017-01-16', 'YYYY-MM-DD')
验证 SQL 从 1900 年到 2100 年检查
需要创建临时文件的能力table
-- need the ability to create a temporary table
drop table #CALWEEK_TEST;
create local temporary table #CALWEEK_TEST as (
select date_sap, YEAR(date_sap) as year_date_sap, WEEKDAY(date_sap) as weekday_date_sap, WEEK(date_sap) as SAPWEEK,
(CASE
-- subtract by 1 when week starts on a Sunday like in 2017
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) != 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap) - 1)
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) = 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap))
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap)) THEN CONCAT(YEAR(date_sap), WEEK(ADD_DAYS(date_sap, 1)) - 1)
when ((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) != 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap))
when ((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) = 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap) + 1)
when YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap)) THEN CONCAT(YEAR(date_sap), WEEK(ADD_DAYS(date_sap, 1)))
END) AS CALWEEK
from "_SYS_BI"."M_TIME_DIMENSION"
-- to eliminate missing values (appears as "?")
where date_sap >= TO_DATE('1900-01-01', 'YYYY-MM-DD')
and date_sap <= TO_DATE('2100-12-31', 'YYYY-MM-DD')
order by date_sap
);
-- 检查每个 CALWEEK 的记录数是否始终为 1 - 7 => 成功
select distinct count(*) as RECORDS_PER_CALWEEK from #CALWEEK_TEST
group by CALWEEK;
-- 检查是否有任何异常的 CALWEEK 值(预计为 1 - 53)=> 成功
select distinct SUBSTRING(CALWEEK, 5) as WEEKONLY from #CALWEEK_TEST
order by WEEKONLY;
这里是一个较短的变体,考虑到年开始时的极端情况,不需要助手 table:
CREATE OR replace FUNCTION week_sunday(DATE date) RETURNS ret integer AS BEGIN
ret = CASE weekday(extract(YEAR FROM date)||'-01-01')
WHEN 6 THEN
CASE weekday(date)
WHEN 6 THEN week(date)
ELSE week(date)-1
END
ELSE
CASE weekday(date)
WHEN 6 THEN week(date)+1
ELSE week(date)
END
END;
END;
业务需要一周从周日开始,但 SAP HANA SQL WEEK() 从周一开始。我如何在星期日开始日历周?我发现一些网页表明这是一个问题,例如 this one,但没有解决方案。
这里的 CALWEEK 已经在 table 中了,所以我会关注 CALWEEK_DERIVED。
创建函数:
CREATE OR REPLACE FUNCTION non_iso_week(in_date DATE)
RETURNS week INTEGER LANGUAGE SQLSCRIPT AS BEGIN
week := CASE EXTRACT(DOW FROM in_date)
WHEN 0 THEN WEEK(in_date) +1
ELSE WEEK(in_date)
END;
END;
然后:
SELECT DISTINCT
calweek
, non_iso_week(order_date) AS calweek_derived
, order_date
FROM dummy
WHERE order_date >='2020-03-07'
AND order_date <='2020-03-10'
;
以下有效。请注意,派生的 Sunday-starting 周是 CALWEEK 并且存在其他列以协助验证。
此解决方案需要存在“_SYS_BI”。“M_TIME_DIMENSION”,可能必须根据此 website.[=21] 底部的评论生成=]
我在年开始时的星期日(如 2017 年)包括特殊处理 - 查找 WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6
我将在下面进行检查:
- 今年2020
- 边缘情况 1:当一年从星期日开始时
- 边缘情况 2:当一年从星期六开始时
- 验证 SQL 从 1900 年到 2100 年检查
今年2020
-- Current year 2020 started on a Wednesday
select date_sap, YEAR(date_sap) as year_date_sap, WEEKDAY(date_sap) as weekday_date_sap, WEEK(date_sap) as SAPWEEK,
(CASE
-- subtract by 1 when year starts on a Sunday like in 2017
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) != 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap) - 1)
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) = 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap))
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap)) THEN CONCAT(YEAR(date_sap), WEEK(ADD_DAYS(date_sap, 1)) - 1)
when ((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) != 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap))
when ((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) = 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap) + 1)
when YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap)) THEN CONCAT(YEAR(date_sap), WEEK(ADD_DAYS(date_sap, 1)))
END) AS CALWEEK
from "_SYS_BI"."M_TIME_DIMENSION"
-- to eliminate missing values (appears as "?")
where date_sap >= TO_DATE('2019-12-30', 'YYYY-MM-DD')
and date_sap <= TO_DATE('2020-01-14', 'YYYY-MM-DD')
order by date_sap;
边缘情况 1:当一年从星期六开始时
2011 年
-- Same SQL but use:
where date_sap >= TO_DATE('2010-12-20', 'YYYY-MM-DD')
and date_sap <= TO_DATE('2011-01-16', 'YYYY-MM-DD')
边缘情况 2:当一年从星期日开始时
2017 年
-- Same SQL but use:
where date_sap >= TO_DATE('2016-12-20', 'YYYY-MM-DD')
and date_sap <= TO_DATE('2017-01-16', 'YYYY-MM-DD')
验证 SQL 从 1900 年到 2100 年检查
需要创建临时文件的能力table
-- need the ability to create a temporary table
drop table #CALWEEK_TEST;
create local temporary table #CALWEEK_TEST as (
select date_sap, YEAR(date_sap) as year_date_sap, WEEKDAY(date_sap) as weekday_date_sap, WEEK(date_sap) as SAPWEEK,
(CASE
-- subtract by 1 when week starts on a Sunday like in 2017
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) != 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap) - 1)
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) = 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap))
when WEEKDAY(TO_DATE(CONCAT(YEAR(date_sap),'-01-01'), 'YYYY-MM-DD')) = 6 and
YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap)) THEN CONCAT(YEAR(date_sap), WEEK(ADD_DAYS(date_sap, 1)) - 1)
when ((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) != 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap))
when ((YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap) + 1)) and (WEEKDAY(date_sap) = 6)) THEN CONCAT(YEAR(date_sap), WEEK(date_sap) + 1)
when YEAR(ADD_DAYS(date_sap, 1)) = (YEAR(date_sap)) THEN CONCAT(YEAR(date_sap), WEEK(ADD_DAYS(date_sap, 1)))
END) AS CALWEEK
from "_SYS_BI"."M_TIME_DIMENSION"
-- to eliminate missing values (appears as "?")
where date_sap >= TO_DATE('1900-01-01', 'YYYY-MM-DD')
and date_sap <= TO_DATE('2100-12-31', 'YYYY-MM-DD')
order by date_sap
);
-- 检查每个 CALWEEK 的记录数是否始终为 1 - 7 => 成功
select distinct count(*) as RECORDS_PER_CALWEEK from #CALWEEK_TEST
group by CALWEEK;
-- 检查是否有任何异常的 CALWEEK 值(预计为 1 - 53)=> 成功
select distinct SUBSTRING(CALWEEK, 5) as WEEKONLY from #CALWEEK_TEST
order by WEEKONLY;
这里是一个较短的变体,考虑到年开始时的极端情况,不需要助手 table:
CREATE OR replace FUNCTION week_sunday(DATE date) RETURNS ret integer AS BEGIN
ret = CASE weekday(extract(YEAR FROM date)||'-01-01')
WHEN 6 THEN
CASE weekday(date)
WHEN 6 THEN week(date)
ELSE week(date)-1
END
ELSE
CASE weekday(date)
WHEN 6 THEN week(date)+1
ELSE week(date)
END
END;
END;