在WHERE子句中使用CASE

时间:2018-08-17 20:42:14

标签: sql sql-server tsql

我有2个表需要基于几个参数进行连接。参数之一是年份。一个表包含当前年份,但是另一年不包含当前年份,因此它必须使用最新年份并与其他参数匹配。

示例

产品

-------------------------------------------------------------------------------
| product_id | category_id | sub_category_id | product_year | amount |
-------------------------------------------------------------------------------
| 504        | I           | U               | 2020         | 400    |
| 510        | I           | U               | 2019         | 100    |
| 528        | I           | U               | 2019         | 150    |
| 540        | I           | U               | 2018         | 1000   |

折扣

-----------------------------------------------------------------------------
| discount_year | category_id | sub_category_id | discount |
-----------------------------------------------------------------------------
| 2018          | I           | U               | 0.15     |
| 2017          | I           | U               | 0.35     |
| 2016          | I           | U               | 0.50     |

输出

-----------------------------------------------------------------------------
| product_id | category_id | sub_category_id | product_year | discount_year |
-----------------------------------------------------------------------------
| 504        | I           | U               | 2020         | 2018          |
| 510        | I           | U               | 2019         | 2018          |
| 528        | I           | U               | 2019         | 2018          |
| 540        | I           | U               | 2018         | 2017          |

总是从一年后开始享受折扣,但是如果没有这些价格,它将一直追溯到一年之前。

我尝试了以下方法:

SELECT 
    product_year, a.product_id, a.category_id, a.sub_category_id, 
    discount_year, amount, discount
FROM
    Product a
INNER JOIN 
    Discount b ON a.category_id = b.category_id 
               AND a.sub_category_id  = b.sub_category_id
               AND product_ year = CASE
                                      WHEN discount_year + 1 = product_year 
                                         THEN discount_year + 1
                                      WHEN discount_year + 2 = product_year 
                                         THEN discount_year + 2
                                      WHEN discount_year + 3 = product_year 
                                         THEN discount_year + 3
                                   END
 WHERE 
     product = 540

这将返回以下输出:

--------------------------------------------------------------------------------------------------
| product_year | product_id | category_id | sub_category_id | discount_year | amount | discount |
--------------------------------------------------------------------------------------------------
| 2016         | 540        | I           | U               | 2017          | 1000   | 0.50     |
| 2017         | 540        | I           | U               | 2017          | 1000   | 0.35     |

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

您可以使用OUTER APPLY和一个子查询。在子查询中,选择最大discount_year的行,使用product_yearTOP减去ORDER BY

SELECT p.product_year,
       p.product_id,
       p.category_id,
       p.sub_category_id,
       d.discount_year,
       p.amount,
       d.discount
       FROM product p
            OUTER APPLY (SELECT TOP 1
                                *
                                FROM discount d
                                WHERE d.category_id = p.category_id
                                      AND d.sub_category_id = p.sub_category_id
                                      AND d.discount_year < p.product_year
                                ORDER BY d.discount_year DESC) d;

答案 1 :(得分:0)

代替CASE表达式,您可以使用子查询选择与TOP 1相关的  discount_year小于您的product_year,或按discount_year ASC排序。

答案 2 :(得分:0)

首先使用CTE创建产品以打折映射。这包含产品表中每个产品年度从折扣表中提取的折扣年度以及相应的product_id。然后,您可以轻松地与相关表连接以获得结果并根据需要消除任何空值

简化查询。

 ;WITH disc_prod_mapper 
    AS
    (
    SELECT  product_id, product_year,(SELECT MAX(discount_year) FROM  #Discount b WHERE discount_year < product_year AND a.category_id  = b.category_id  AND a.sub_category_id   = b.sub_category_id ) AS discount_year
     FROM Product a  
    )
    SELECT a.product_year, c.discount_year, a.amount, c.discount
    FROM Product a
      LEFT JOIN disc_prod_mapper b   ON a.product_id  = b.product_id   
      LEFT JOIN Discount c ON b.discount_year = c.discount_year