带有条件的CASE声明

时间:2017-01-10 03:02:58

标签: sql-server sql-server-2012 case

我认为首先展示一个例子会更容易解释:

SELECT P.ID,
(CASE WHEN PC.NewCostPrice IS NULL 
THEN P.Cost ELSE MAX(PC.Date) PC.NewCostPrice
END)
FROM price AS P
LEFT OUTER JOIN priceChange as PC
ON P.ID = PC.ID

所以在这个例子中,如果NewCostPrice是NULL,意味着没有价格变化,那么我想要正常成本(P.Cost)。但是,如果价格发生变化,我想要最近的(MAX(日期))价格变动。我不知道如何将其纳入CASE声明。

我觉得可以使用子查询和子句来完成,但是当我尝试时它并没有真正解决。有什么建议?

谢谢!

4 个答案:

答案 0 :(得分:3)

您可以考虑两种方法 - 我会测试两种方法,看看哪种方式对您的情况有更好的效果。

  1. 在子查询中使用ROW_NUMBER()查找所有价格变化的最新价格变化,然后将其加入价格以获得正确的价格。
  2. 使用相关子查询(许多方式,在SELECT中与其他答案一样,或与OUTER APPLY一起使用),只获得每行价格的最新价格变动
  3. 如果您的价格表非常大并且您一次获得大量价格,方法#1可能会更好,因此相关子查询不会为结果集的每一行运行。

    如果您的最终查询为您的服务器提取了相对较少数量的记录而不是大量结果集,那么相关子查询可能会更适合您。

    <强> 1。 ROW_NUMBER()方法

    SELECT
        P.ID,
        COALESCE(PC.NewCostPrice, P.Cost) AS LatestPrice
    FROM Price AS P
        LEFT OUTER JOIN (
            SELECT
                ID,
                ROW_NUMBER() OVER (PARTITION BY ID
                    ORDER BY [Date] DESC) AS RowId,
                NewCostPrice
            FROM PriceChange
        ) PC
            ON P.ID = PC.ID
                AND PC.RowId = 1 -- Only most recent
    

    <强> 2a上。相关子查询(SELECT

    SELECT
        P.ID,
        COALESCE((
            SELECT TOP 1
                NewCostPrice
            FROM PriceChange PC
            WHERE PC.ID = P.ID
            ORDER BY PC.[Date] DESC
        ), P.Cost) AS LatestPrice
    FROM Price AS P
    

    <强> 2B。相关子查询与OUTER APPLY

    SELECT
        P.ID,
        COALESCE(PC.NewCostPrice, P.Cost) AS LatestPrice
    FROM Price AS P
        OUTER APPLY (
            SELECT TOP 1
                NewCostPrice
            FROM PriceChange PC
            WHERE PC.ID = P.ID
            ORDER BY PC.[Date] DESC
        ) PC
    

    无论您使用2a还是2b,都更倾向于您希望如何继续维护查询。

答案 1 :(得分:2)

简单方法

SELECT   distinct P.ID,
    ISNULL((SELECT TOP 1 PC1.NewCostPrice FROM  priceChange as PC1 WHERE PC1.ID = p.id ORDER BY PC1.Date DESC), p.cost)
    FROM price AS P

答案 2 :(得分:0)

我假设PC.ID不是主键,或者加入ID没有任何意义,而同一项目的价格可能不同。

根据您的查询,我假设您只想通过加入NewCostPrice

来获取按Date排序的最新priceChange
SELECT
    P.ID,
    CASE
        WHEN PC.NewCostPrice IS NULL THEN P.Cost
        ELSE PC.NewCostPrice                    
    END AS NewPrice
FROM
    price AS P
LEFT JOIN 
    (SELECT *, RANK() OVER (PARTITION BY ID ORDER BY [Date] DESC) as rk FROM priceChange) PC ON P.ID = PC.ID AND PC.rk = 1 

答案 3 :(得分:-1)

    SELECT   P.ID
            ,(CASE 
                WHEN PC.NewCostPrice IS NULL 
                  THEN P.Cost 
                ELSE (SELECT TOP 1 PC1.NewCostPrice
                      FROM  priceChange PC1
                      WHERE PC1.ID = PC.ID
                      GROUP BY  PC1.NewCostPrice, PC1.Date
ORDER BY PC1.Date DESC
                      )
               END
              )
    FROM price AS P
    LEFT OUTER JOIN priceChange as PC
    ON P.ID = PC.ID