为没有联合的每一行选择x次

时间:2011-03-03 18:44:47

标签: sql sql-server tsql union-all

是否可以更简单地编写如下所示的联合选择查询?

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

该语句为Products表中的每一行选择四行。唯一不同的是用于计算第二列和树的值的公式。我认为应该有一种方法在sql中编写上面没有那么多丑陋的代码重复。如果只有函数是第一类对象而sql允许使用lambda表达式......

理查德在下面的解决方案是完美的,对于提供的示例非常有效。但是我在orignal例子中有两个拼写错误,这使问题变得更加困难:

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

最大的问题是比较运算符不同的case表达式。我的问题是,“整齐地”处理这些案件非常困难。如果有第三种情况比较是p.Paydate = getdate(),该怎么办?

2 个答案:

答案 0 :(得分:3)

(不确定lambda表达式如何帮助你)

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。

答案 1 :(得分:0)

如果订单无关紧要,您可以使用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)
  )
)