0

I now have an intermediate view in SQL Server, and a final view, as follows:

Intermediate view:

SELECT
    ....
    ElapsedDays = DATEDIFF(d, ri.DateReceived, GETDATE()),
    .....
FROM 
    RegionalInventory AS ri

Final view:

SELECT
    ....
    PenaltyBucket = COALESCE(CASE WHEN inv.ElapsedDays <= 30 THEN 'Not Late' END,
                             CASE WHEN inv.ElapsedDays > 30 THEN 'Late' END)
    ....
FROM 
    Inventory AS inv

I am wondering if there's a way for me to combine both views into one, but I am not sure how to declare a variable to hold the value of ElapsedDays, and then use it to set the value for the ElapsedDays column and to do the logical test, to both create the PenaltyBucket column and fill it with the right value.

3 Answers 3

4

Assuming that you really have only one table (called RegionalInventory, this is a convenient place for a lateral join:

SELECT . . ., v.ElapsedDays,
       (CASE WHEN v.ElapsedDays <= 30 THEN 'Not Late'
             WHEN v.ElapsedDays > 30 THEN 'Late'
        END) as PenaltyBucket
FROM RegionalInventory ri CROSS APPLY
     (VALUES (DATEDIFF(day, ri.DateReceived, GETDATE()))
     ) v(ElapsedDays);

Note:

  • There is no need to use COALESCE() with two CASE expressions. One CASE can handle multiple conditions.
  • Spell out day when using DATEDIFF(). That is just a good habit (consider: does m mean minutes or months?)
Sign up to request clarification or add additional context in comments.

2 Comments

I actually have more than two CASE expressions, but listed only two here for brevity and I am only dealing with one table. I till test this out
@coyotepoint . . . The values clause can define multiple columns: (values ( . . . , . . . , . . .)) v(a, b, c).
3

You can just repeat the expression in the SELECT clause:

SELECT
    ...,
    DATEDIFF(d, ri.DateReceived, GETDATE()) AS ElapsedDays,
    CASE 
        WHEN DATEDIFF(d, ri.DateReceived, GETDATE()) <= 30 then 'Not Late'
        ELSE 'Late' 
    END AS PenaltyBucket 
    ...
FROM RegionalInventory as ri

Alternatively, you can use a subquery:

SELECT
    t.*,
    CASE 
        WHEN ElapsedDays  <= 30 then 'Not Late'
        ELSE 'Late' 
    END AS PenaltyBucket 
FROM (
    SELECT
        ...,
        DATEDIFF(d, ri.DateReceived, GETDATE()) AS ElapsedDays,
        ...
    FROM RegionalInventory as ri
) t

Comments

1

You can define inner view as a CTE and then refer it again.

CREATE VIEW [ schema_name . ] view_name [ ( column_name [ ,...n ] ) ] AS <select_statement> [;] <select_statement> ::=
[ WITH <common_table_expression> [ ,...n ] ]
SELECT <select_criteria>

Below is demo code for your reference.

create view vw_test
as 
WITH cte_1 as
(
select 1 as a
)
SELECT t.testname
from (values (1,'test1'),(2,'test2')) as t(a,testname)
join cte_1 as c
on c.a = t.a

select * from vw_test

What you can do is. Sample code for your reference.

CREATE VIEW outerView
AS
WITH cte_innerview
as
(
SELECT
    ....
    ElapsedDays = DATEDIFF(d, ri.DateReceived, GETDATE()),
    .....
FROM 
    RegionalInventory AS ri
)
SELECT
    ....
    PenaltyBucket = COALESCE(CASE WHEN inv.ElapsedDays <= 30 THEN 'Not Late' END,
                             CASE WHEN inv.ElapsedDays > 30 THEN 'Late' END)
    ....
FROM 
    Inventory AS inv
INNER JOIN cte_innerview as c
on c.InventoryId = inv.InventoryId

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.