DB2 Как преобразовать следующее «с temp as» в обычный оператор выбора - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь выполнить вставку с этим оператором «with», но похоже, что он поддерживает только оператор SELECT, поэтому я хочу преобразовать его в оператор SELECT.Я просто поражен тем, как это работает.Получил похожий пример в стеке и изменил его в соответствии со своими потребностями.

with temp (startdate, enddate, maxdate) as (
    select min(salesdate) startdate, min(salesdate)+3 months enddate, max(salesdate) maxdate
    from SALES
    union all
    select startdate + 3 months + 1 days, enddate + 3 months + 1 days, maxdate from temp 
    where enddate <= maxdate
)
select startdate, min(enddate, maxdate) from temp;

Заранее спасибо.

Редактировать : Кажется, мой запрос неправильно понят.Вот псевдокод того, что должен делать запрос.Запрос возвращает ожидаемый результат, что довольно удивительно для меня.Я не знаю, как рекурсив не перекрывается после того, как я добавил 1 день.После написания псевдокода я вижу, что select startdate + 3 months + 1 days должен был быть записан как select enddate + 1 days, который логически говорит, что он должен делать вместо магической работы:

rows = []
startdate = min(salesdate)
enddate = startdate + 3 months
maxdate = max(salesdate)
i = 0;
do {
    rows[i++] = [startdate, min(enddate, maxdate)] // min for final iteration where enddate > maxdate.
    startdate = enddate + 1 days
    enddate = enddate + 1 days + 3 months // aka: startdate + 3 months
} while (enddate <= maxdate)
return rows

Следовательно, я сломалогромный диапазон дат на более мелкие куски по 3 месяца.Неважно, будет ли это 90 дней или 91 день, если я получаю каждую дату без перерыва и без наложения.

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Мне интересно ваше решение, что запрос с рекурсивным общим табличным выражением (RCTE) является "ненормальным".IBM называет его «оператором выбора» и считает его нормальным.Если это какой-то образовательный вопрос, и вы не хотите использовать RCTE по какой-либо причине, рассмотрите следующий пример.

select s + (3*(x.i-1)) month start, s + (3*x.i) month - 1 day end
from table(values (date('2011-01-01'), date('2012-01-01'))) d(s, e)
, xmltable('for $id in (1 to $e) return <i>{number($id)}</i>' 
  passing ((year(e)-year(s))*12 + (month(e)-month(s)))/3 as "e"
  columns i int path '.'
) x;

START       END
----------  ----------
2011-01-01  2011-03-31
2011-04-01  2011-06-30
2011-07-01  2011-09-30
2011-10-01  2011-12-31
;

Это немного сложно, так как вы должны передать желаемое количество строкчтобы вернуться к табличной функции xmltable, которая возвращает один столбец со значениями от 1 до N. Другими словами, вы должны вычислить желаемое количество 3-месячных интервалов и передать его функции.

(R) CTE можетне использоваться в операторах UPDATE / DELETE, где вы можете использовать только так называемые операторы полной выборки (они не допускают CTE).Если вам действительно нужно использовать CTE для UPDATE / DELETE, как в этом случае, вы можете выполнить одно из следующих действий:

Если вы способны вычислить временный набор результатов для всего оператора delete / update, вы можете сделатьчто-то вроде этого (я не использую здесь RCTE для простоты, но только для простого CTE):

with a (id) as (values 1)
select count(1)
from old table(
delete from test t 
where exists (select 1 from a where a.id=t.id)
);

Если вы НЕ МОЖЕТЕ вычислить временный набор результатов для всего оператора delete / update, вы можетесоздайте табличную / скалярную функцию с соответствующими параметрами, где вы сможете использовать свой RCTE.Впоследствии эта функция может использоваться во внешнем выражении.

0 голосов
/ 27 ноября 2018

Мне удалось вставить его, переместив оператор вставки перед оператором «с».Копирую ответ сюда, чтобы я знал в следующий раз.Хотя мне все еще интересно узнать, как преобразовать его в чистый оператор выбора.Выберет этот ответ как правильный ответ.

insert into my_temp_table
    with temp (startdate, enddate, maxdate) as (
      select min(salesdate) startdate, min(salesdate)+3 months enddate, max(salesdate) maxdate
      from SALES
      union all
      select startdate + 3 months + 1 days, enddate + 3 months + 1 days, maxdate from temp 
      where enddate <= maxdate
   )
   select startdate, min(enddate, maxdate) from temp;
...