2015-04-28 3 views
1

Я пытаюсь создать запрос, чтобы создать диапазон дат между конкретной начальной и конечной точкой.Рекурсивный запрос для диапазона дат

У меня есть следующие:

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.

Как бы переписать этот запрос, чтобы выполнить это?

+0

Сторона примечания: типы даты/времени/времени, как и все положительные, континуальные диапазоны (все, кроме явного цельного числа), должны запрашиваться с помощью эксклюзивной верхней границы. [Это сообщение в блоге] (http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do-between-and-the-devil-have-in-common.aspx) имеет дело с SQL Server , но проблема на самом деле связана с тем, как цифры представлены в целом (это не проблема на самом деле). О, и в DB2 вы можете указать количество дробных секунд для метки времени, поэтому оно будет применяться в любом случае. –

ответ

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“может содержать бесконечный цикл»), что я пока не выяснили, но выборка работает, окончательное возвращение происходит с 04-01 до 05-01. Надеюсь, вы можете перенести это на нужный язык.

+0

Линия 'SELECT CAST (? AS DATE)' фактически была тем, чего я хотел, хотя я этого плохо спросил. Применение этого к моему первоначальному запросу было именно тем, чего я хотел. – Cameron

+0

Вам понадобится только бросок, если пармы не являются датами для начала. Если '@ End' сам работал в вашем оригинале, тогда' @ Str' также работал бы сам, как и в моем ответе. – Charles

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, ect .., которые значительно облегчают жизнь.

Google "SQL calendar table" для множества примеров.

+0

Спасибо за ваше решение. Создание таблицы для дат в моей ситуации не является вариантом. – Cameron

+0

Почему бы и нет? Если ответ аналогичен «Я разработчик, администраторы баз данных не позволят мне создавать таблицы», тогда спросите, существует ли он уже. Если нет, попросите их создать его. – Charles

+1

@Cameron - Секундный календарь. Это, руки, самая полезная таблица измерений/анализа, которую вы можете сделать.При правильной индексации (и поскольку они не обновляются, у вас может быть столько, сколько вы захотите), вы можете получить запросы на основе индексов, чтобы спросить практически о каком-то временном вопросе, о котором вы можете подумать, - о том, что вы обычно нужны вызовы функций. –

Смежные вопросы