给定两个日期,我想创建一个数组来保存这些日期之间的所有天数,然后过滤它以仅包含月末的天数。
例如,使用start_date
2019-01-31
and end_date
2019-06-30
,我会构造数组
[
'2019-01-31',
'2019-02-28',
'2019-03-31',
'2019-04-30',
'2019-05-31',
'2019-06-30'
]
给定两个日期,我想创建一个数组来保存这些日期之间的所有天数,然后过滤它以仅包含月末的天数。
例如,使用start_date
2019-01-31
and end_date
2019-06-30
,我会构造数组
[
'2019-01-31',
'2019-02-28',
'2019-03-31',
'2019-04-30',
'2019-05-31',
'2019-06-30'
]
很难准确理解您想要什么,但从请求的输出来看,该数组似乎包含两个日期限制之间的每月日期。我尝试使用 JavaScript 来实现以避免可怕的“不支持的子查询”错误,但是很难计算日期、格式化它们并从 JavaScript 返回到 SQL。
所以我最终得到了一个 SQL UDF:
CREATE OR REPLACE FUNCTION ARRAY_MONTHS_BETWEEN("FROM" DATE, "TO" DATE)
RETURNS ARRAY AS
'
SELECT ARRAY_AGG(DATEADD(MONTH, "MONTH" , "FROM")) A
FROM (SELECT ROW_NUMBER() OVER (ORDER BY NULL) - 1 "MONTH"
FROM TABLE(GENERATOR(ROWCOUNT => 1000)))
WHERE "MONTH" <= CEIL(DATEDIFF(MONTHS, "FROM", "TO"))
';
除了日期常量外,使用此函数可能会很棘手,因为您可能会打开雪花相关子查询的潘多拉魔盒。但话又说回来,也许不是。
Snowflake LAST_DAY函数可用于获取两个日期之间的每个月的最后一天 https://docs.snowflake.net/manuals/sql-reference/functions/last_day.html。
SELECT
ARRAY_AGG(LAST_DAY(MY_DATE))
FROM (
SELECT
LAST_DAY(DATEADD(MONTH, SEQ4(), '2019-01-31')) AS MY_DATE
FROM TABLE(GENERATOR(ROWCOUNT=>20000))
WHERE MY_DATE <= '2019-06-30'
);
上面的查询还将结果包装在一个数组中https://docs.snowflake.net/manuals/sql-reference/functions/array_agg.html
[
"2019-01-31",
"2019-02-28",
"2019-03-31",
"2019-04-30",
"2019-05-31",
"2019-06-30"
]
如前所述,您可以选择使用此 sql 来创建新的用户定义函数:
CREATE FUNCTION LAST_DATES_TO_ARRAY(FROM_D DATE, TO_D DATE)
RETURNS ARRAY
AS
$$
SELECT ARRAY_AGG(LAST_DAY(MY_DATE))
FROM (
SELECT
LAST_DAY(DATEADD(MONTH, SEQ4(), FROM_D)) AS MY_DATE
FROM TABLE(GENERATOR(ROWCOUNT=>20000))
WHERE MY_DATE <= TO_D
)
$$;
基于先前响应者提供的内容,以下内容应该对您有用。
CREATE OR REPLACE FUNCTION LAST_DATES_TO_ARRAY(FROM_DT DATE, TO_DT DATE)
RETURNS ARRAY
AS
$$
SELECT ARRAY_AGG(DISTINCT LAST_DAY(MY_DATE))
FROM (
SELECT
LAST_DAY(DATEADD(MONTH, SEQ4(), FROM_DT)) AS MY_DATE
FROM TABLE(GENERATOR(ROWCOUNT=>2000000))
WHERE MY_DATE <= TO_DT
ORDER BY 1
)
$$;
SELECT LAST_DATES_TO_ARRAY(DATEADD('YEARS', -1, CURRENT_DATE()), CURRENT_DATE()) AS my_array;
MY_ARRAY
["2018-11-30",
"2018-12-31",
"2019-01-31",
"2019-02-28",
"2019-03-31",
"2019-04-30",
"2019-05-31",
"2019-06-30",
"2019-07-31",
"2019-08-31",
"2019-09-30",
"2019-10-31"]
另一种仅 sql 的解决方案 - 开始和结束日期进入 current_date() 点。
生成 10000 年的所有月末将今天放在中间 (365|180 * 10000) 非常快,然后只需在放入数组之前使用 sed 开始和结束日期来预测答案。运行时间为 202 毫秒
没有功能,使用缓存,更少的测试等。
select array_agg(distinct my_date)
from (
SELECT
last_day( DATEADD(DAY, -1*SEQ4(), CURRENT_DATE()+(180*10000)),month) AS MY_DATE
FROM TABLE(GENERATOR(ROWCOUNT => (365*10000) ))
where
my_date between
current_date() -39 and
current_date() +80
)