Question

How can I avoid having to type the same CASE WHEN... over and over in a WHERE clause?

CASE WHEN rawGlass.blockHeight > rawGlass.blockWidth THEN rawGlass.blockWidth ELSE rawGlass.blockHeight END repeats quite frequently in this query. I'd like to only have to do that once. I already know referencing [Glass Height] in the WHERE clause will result in an Invalid column... error.

I realize there may be other solutions that don't involve using a CASE WHEN that will work for this particular instance and I welcome them, but I would really like an answer to the question at hand since I've come across this problem before with other queries.

SELECT
    parts.pgwName AS [Part Name],
    parts.active AS [Active],
    cutVinyl.boardName AS [Vinyl Board],
    cutVinyl.rollWidth AS [Roll Width],
    CASE WHEN rawGlass.blockHeight > rawGlass.blockWidth THEN rawGlass.blockWidth ELSE rawGlass.blockHeight END AS [Glass Height]
FROM
    parts
        LEFT JOIN cutVinyl ON parts.vinylBoard = cutVinyl.boardName
        LEFT JOIN rawGlass ON parts.outerSku = rawGlass.sku
WHERE
    (
        (cutVinyl.stretchRadius IS NOT NULL OR cutVinyl.stretchRadius = 0) AND 
        cutVinyl.rollWidth < (CASE WHEN rawGlass.blockHeight > rawGlass.blockWidth THEN rawGlass.blockWidth ELSE rawGlass.blockHeight END)
    ) ...


Note: The list of conditions goes on a while, so wrapping the whole WHERE clause in one CASE WHEN... statement and then repeating the conditions twice doesn't really help any.

Was it helpful?

Solution

Use CROSS APPLY

SELECT
    pgwName AS [Part Name],
    active AS [Active],
    boardName AS [Vinyl Board],
    rollWidth AS [Roll Width],
    [Glass Height]
FROM
    parts
        LEFT JOIN cutVinyl ON parts.vinylBoard = cutVinyl.boardName
        LEFT JOIN rawGlass ON parts.outerSku = rawGlass.sku
        CROSS APPLY (
            SELECT CASE WHEN blockHeight > blockWidth THEN blockWidth 
                                                      ELSE blockHeight 
                   END AS [Glass Height]
        ) AS CA1
WHERE
    (
        (stretchRadius IS NOT NULL OR stretchRadius = 0) AND 
        rollWidth < [Glass Height])
    ) ...

OTHER TIPS

You can choose to write an outer query with current as a sub-query like this:

SELECT * FROM
(
    SELECT
    pgwName AS [Part Name],
    active AS [Active],
    boardName AS [Vinyl Board],
    rollWidth AS [Roll Width],
    CASE WHEN blockHeight > blockWidth THEN blockWidth ELSE blockHeight END AS [Glass Height]
    FROM
    parts
        LEFT JOIN cutVinyl ON parts.vinylBoard = cutVinyl.boardName
        LEFT JOIN rawGlass ON parts.outerSku = rawGlass.sku

) out
WHERE
    (
        (stretchRadius IS NOT NULL OR stretchRadius = 0) AND 
         rollWidth < Glass Height    
   ) ...

I'm guessing the part table is where that case statement comes from:

...
FROM
 parts
    LEFT JOIN cutVinyl ON parts.vinylBoard = cutVinyl.boardName
    LEFT JOIN (select * 
              , CASE WHEN blockHeight > blockWidth THEN blockWidth 
                ELSE blockHeight 
                END AS [Glass_Height] from rawglass) rawGlass ON parts.outerSku = rawGlass.sku
...

Now you can refer to glass_height in the select statement or where statement as needed.

You could use a custom table expression (CTE):

;WITH MyCTE AS (
SELECT
    pgwName,
    active,
    boardName,
    rollWidth,
    CASE WHEN blockHeight > blockWidth THEN blockWidth ELSE blockHeight END AS GlassHeight,
    stretchRadius,
    rollWidth

FROM
    parts
        LEFT JOIN cutVinyl ON parts.vinylBoard = cutVinyl.boardName
        LEFT JOIN rawGlass ON parts.outerSku = rawGlass.sku
)
SELECT
    pgwName AS [Part Name],
    active AS [Active],
    boardName AS [Vinyl Board],
    rollWidth AS [Roll Width],
    GlassHeight AS [Glass Height]
FROM MyCTE        
WHERE
    (
        (stretchRadius IS NOT NULL OR stretchRadius = 0) AND 
        rollWidth < GlassHeight 
    )

Think of CTE as disposable, chainable views. They are very useful when you need to define subsets of data to be reused in your final query. Once the latter is executed they cease to exist. Their performance cost is virtually non-existant.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top