日期范围的递归查询

时间:2015-04-28 15:47:18

标签: sql db2

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

我有以下内容:

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注入的查询。

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

2 个答案:

答案 0 :(得分:2)

您的SELECT很好,除了硬编码的开始日期。

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

但是,不要动态生成这个日期范围....考虑简单地创建一个日历(又名日期)表。基本上只是一张桌子,日期从1900-01-01到2500-12-31 ......或者你喜欢什么。在日期列旁边,您可以添加许多其他列,例如business_day,holiday等等,这些列可以让生活更轻松。

谷歌“SQL日历表”有很多例子。

答案 1 :(得分:1)

在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);

这确实在准备期间出现错误(“递归公用表表达式”MYSCHEMA.DATE_RANGE“可能包含无限循环”)我还没想到,但是fetch确实有效,最终返回从04开始-01至05-01。希望您可以将其移植到您想要的语言。