日期范围的递归查询

Recursive Query for Date Range

我正在尝试创建一个查询,以便生成特定起点和终点之间的日期范围。

我有以下内容:

WITH DATE_RANGE(DATE_FOR_SHIFT)
     AS (SELECT DATE('2015-04-01')
         FROM   SYSIBM.SYSDUMMY1
         UNION ALL
         SELECT DATE_FOR_SHIFT + 1 DAY
         FROM   DATE_RANGE
         WHERE  DATE_FOR_SHIFT <= @END)
SELECT DATE_FOR_SHIFT
FROM   DATE_RANGE;

输出(假设@END等于2015-05-01):

2015-04-01
2015-04-02
2015-04-03
2015-04-04
...
2015-05-01

输出是正确的,但我希望能够根据提供的参数更改起点和点,而不必重写查询或使用 SQL 容易注入的查询。

我将如何重写此查询以实现此目的?

在 perl 中稍微玩一下这个给了我:

#!/opt/myperl/5.20.2/bin/perl

use 5.10.0;
use DBI;
use DBD::DB2;
use Data::Dump;

my $sql = <<EOSQL;

WITH DATE_RANGE(DATE_FOR_SHIFT)
     AS (SELECT CAST(? AS DATE)
         FROM   SYSIBM.SYSDUMMY1
         UNION ALL
         SELECT DATE_FOR_SHIFT + 1 DAY
         FROM   DATE_RANGE
         WHERE  DATE_FOR_SHIFT < CAST(? AS DATE))
SELECT DATE_FOR_SHIFT
FROM   DATE_RANGE;

EOSQL


my $dbh = DBI->connect('dbi:DB2:sample');
my $sth = $dbh->prepare_cached($sql);
$sth->execute('2015-04-01','2015-05-01');
my $rc = $sth->fetchall_arrayref();
dd($rc);

这确实在准备期间给出了一个错误("The recursive common table expression "MYSCHEMA.DATE_RANGE“可能包含一个无限循环”),我还没有弄清楚,但是提取确实有效,最后的 return 从 04-01 到 05-01。希望您可以将其移植到您想要的语言。

你的 SELECT 没问题,除了硬编码的开始日期。

我认为您缺少的是将其包装在存储过程或用户定义的 table 函数 (UDTF) 中。假设您想要加入其他 table 的日期范围,我建议使用 UDTF。

create function date_range (@str date, @end date) 
returns table (date_for_shift date) 
language SQL
reads SQL data
return
   WITH DATE_RANGE(DATE_FOR_SHIFT)
     AS (SELECT @str
         FROM   SYSIBM.SYSDUMMY1
         UNION ALL
         SELECT DATE_FOR_SHIFT + 1 DAY
         FROM   DATE_RANGE
         WHERE  DATE_FOR_SHIFT <= @END)
    SELECT DATE_FOR_SHIFT
    FROM   DATE_RANGE;

那你就叫它...

select * from table(date_range(date('2015-04-01'),date('2015-05-01'))) as tbl;

但是,与其动态生成此日期范围,不如考虑简单地创建一个日历(又名日期)table。基本上只是一个 table,日期从 1900-01-01 到 2500-12-31.. 或者任何你想要的。除了日期列之外,您还可以包含许多其他列,例如 business_day、假期等,让生活变得更轻松。

Google "SQL calendar table" 有很多例子。