Kumaran S
Kumaran S

Reputation: 131

Using CASE in WHERE clause

I have 2 tables that needs to be joined based on couple of parameters. One of the parameters is year. One table contains the current year but another year doesn't contain current year, so it must use the latest year and matched with other parameters.

Example

Product

-------------------------------------------------------------------------------
| 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

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

Output

-----------------------------------------------------------------------------
| 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          |

The discount is always gotten from one year behind but if those rates aren't available, then it would keep going back a year until available.

I have tried the following:

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

This return the following output:

--------------------------------------------------------------------------------------------------
| 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     |

Any help will be appreciated.

Upvotes: 1

Views: 87

Answers (3)

J Sidhu
J Sidhu

Reputation: 677

Create a product to discount mapping using a CTE first. This contains the discount year pulled from discount table for every product year in the product table and corresponding product_id. Following this, you can easily join with relevant tables to get results and eliminate any nulls as needed

Simplified query.

 ;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

Upvotes: 0

sticky bit
sticky bit

Reputation: 37472

You can use OUTER APPLY and a subquery. In the subquery select the row with the maximum discount_year, that is less the product_year using TOP and 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;

Upvotes: 1

Tab Alleman
Tab Alleman

Reputation: 31775

instead of a CASE expression you can use a sub-query to select the TOP 1 related discount_year that is less than your product_year, ORDER BY discount_year ASC.

Upvotes: 0

Related Questions