Выберите x раз для каждой строки без объединения - PullRequest
0 голосов
/ 03 марта 2011

Можно ли более кратко написать запросы на объединение, например, следующие?

select
    id,
    1,
    (1 + @defCapUp) * (p.Value + p.Premium),
    getdate()
from Products p
union
select
    id,
    1,
    (1 - @defCapDown) * (p.Value - p.Premium),
    getdate()
from Products p
union
select
    id,
    case when p.Paydate > getdate() then 1 else 0 end,
    (1 - @defCapUp) * (p.Value - p.Premium),
    @nextYear
from Products p
union
select
    id,
    case when p.Paydate > getdate() then 1 else 0 end,
    (1 + @defCapDown) * (p.Value + p.Premium),
    @nextYear
from Products p

Оператор выбирает четыре строки для каждой строки в таблице "Продукты".Единственное, что меняется, - это формула, используемая для вычисления значений для второго столбца и дерева.Я думаю, что в SQL должен быть способ написать выше без такого ужасного дублирования кода.Если бы только функции были объектами первого класса, а sql допускало лямбда-выражения ...

Нижеприведенное решение Ричарда прекрасно, очень хорошо работает в представленном примере.Но в оригинальном примере у меня было две опечатки, которые несколько усложняют задачу:

select
    id,
    1,
    (1 + @defCapUp) * (p.Value + p.Premium),
    getdate()
from Products p
union
select
    id,
    1,
    (1 - @defCapDown) * (p.Value - p.Payout),
    getdate()
from Products p
union
select
    id,
    case when p.Paydate > getdate() then 1 else 0 end,
    (1 - @defCapUp) * (p.Value - p.Premium),
    @nextYear
from Products p
union
select
    id,
    case when p.Paydate <= getdate() then 1 else 0 end,
    (1 + @defCapDown) * (p.Value + p.Payout),
    @nextYear
from Products p

Большая проблема заключается в выражении падежа, в котором оператор сравнения отличается.Моя проблема в том, что очень трудно «аккуратно» разобраться с этими случаями.Что если бы был третий случай, когда сравнение было, например, p.Paydate = getdate ()?

Ответы [ 2 ]

3 голосов
/ 03 марта 2011

(Не уверен, как бы вам помогли лямбда-выражения)

select
    id,
    case when p.Paydate > X.CompareDate then 1 else 0 end,
    (1 + Cap) * (p.Value + ModF * p.Premium),
    @nextYear
from Products p
cross join (
    select @defCapUp Cap, Cast(0 as datetime) CompareDate, 1 Modf union all
    select -@defCapDown, 0, -1 union all
    select -@defCapUp, GETDATE(), -1 union all
    select @defCapDown, GETDATE(), 1
    ) X

Кстати, вы должны были использовать UNION ALL, а не UNION.

0 голосов
/ 03 марта 2011

Если заказ не имеет значения, вы можете использовать WHERE.

SELECT id, field2, field3, field4
FROM Products p
WHERE (
  field4 = getdate() AND field2=1 AND
  (
    field3=(1 + @defCapUp) * (p.Value + p.Premium) OR
    field3=(1 - @defCapDown) * (p.Value - p.Premium)
  )
)
OR
(
  field4=@nextYear AND field2=(case when p.Paydate > getdate() then 1 else 0 end) AND
  (
    field3=(1 - @defCapUp) * (p.Value - p.Premium) OR
    field3=(1 + @defCapDown) * (p.Value + p.Premium)
  )
)
...