Возвращает записи, повторяющиеся в соответствии со значением поля

у меня такая таблица

Name         Qty   
-----        -----
BD             2
SD             1
XE             3

Мне нужно вернуть записи этой таблицы, повторяющиеся в соответствии со значением поля Qty. например, первая строка будет повторяться дважды со всеми одинаковыми значениями.

Я думал использовать вложенную FOR Select внутри хранимой процедуры с возвращаемыми параметрами

For Select name, qty from mytable into :name, :qty do
  begin
    if (qty > 1 ) then begin
      i = 1; -- should I start from 2 ?
      while (i <= :qty) do
      begin

        for select name, qty from mytable into :name1, :qty1 do ...

        SUSPEND;

        i = i + 1;
      end


    end

    SUSPEND;
end

Может ли эта хранимая процедура вернуть правильный результат или мне следует использовать другой способ?

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


person William    schedule 18.10.2013    source источник


Ответы (2)


Вы можете сделать это с помощью рекурсивного CTE., поддерживается с версии 2.1, что-то вроде

WITH RECURSIVE tQty AS(
    SELECT ta.name, ta.qty
       FROM T ta
       WHERE(ta.qty > 0)
 UNION ALL
    SELECT tb.name, tb.qty-1
       FROM tQty tb
       WHERE(tb.qty-1 > 0)
 )
 SELECT name,qty FROM tQty
       ORDER BY name
person ain    schedule 19.10.2013
comment
Выглядит интересно, хотя, если я правильно понимаю, вам нужен anchor (первый подвыбор) и один subselect для каждого уровня рекурсии. Я попробовал ваш выбор с примером OP, и он повторил значение XE только 2 раза. Когда я добавил еще один подвыбор, он повторил это значение 3 раза. Знаете ли вы, есть ли способ сделать это без добавления подзапроса для каждого уровня? - person Guillem Vicens; 19.10.2013
comment
Хм, я проверил это с FB2.5 и получил ожидаемый результат. - person ain; 20.10.2013
comment
У меня есть запись где Qty = 4 но повторяется всего 2 раза. можешь модифицировать? - person William; 20.10.2013
comment
@ain, неважно, у меня в запросе опечатка. Вместо tQty во втором подзапросе я написал T. - person Guillem Vicens; 20.10.2013
comment
@Wel, я думаю, что у вас есть такая же опечатка в вашем запросе, как и у Гиллема - убедитесь, что вы заменили имя таблицы T на реальное только при первом SELECT, другие должны выбрать из tQty. - person ain; 20.10.2013
comment
@ain Да, теперь это работает и очень быстро. Не могли бы вы объяснить, как работает вычитание в tb.qty-1 ? - person William; 21.10.2013
comment
(tb.qty-1 > 0) - это условие, которое останавливает рекурсию. Вызов верхнего уровня — это SELECT из исходной таблицы с исходным значением поля qty, которое передается в рекурсивную часть запроса (tQty). В рекурсивной части из значения количества вычитается единица, и если оно по-прежнему > 0, то выводится строка и вызывается следующий уровень рекурсии с текущим значением количества. - person ain; 21.10.2013

Если у вас есть таблица Numbers, это тривиально:

SELECT
    OT.Name
FROM
    OrigTable AS OT
    INNER JOIN Numbers AS N ON N.Number BETWEEN 1 AND OT.Qty

Я не знаком с Firebird, но надеюсь, что этот очень простой синтаксис применим.

person Community    schedule 18.10.2013