Reputation: 6151
+---------------+------------+
|Processing_date|Contaminated|
+---------------+------------+
|2000/01/01 | FALSE |
|2000/01/02 | TRUE |
|2000/01/03 | FALSE |
|2000/01/04 | FALSE |
+---------------+------------+
I'm trying to figure out how to do a select where I have a column 'ToBeChecked' based on the contaminated column such that ToBeChecked is true for all following rows.
+---------------+------------+------------------+
|Processing_date|Contaminated|item_to_be_checked|
+---------------+------------+------------------+
|2000/01/01 | FALSE |FALSE |
|2000/01/02 | TRUE |TRUE |
|2000/01/03 | FALSE |TRUE |
|2000/01/04 | FALSE |TRUE |
|2000/01/05 | FALSE |TRUE |
+---------------+------------+------------------+
I figure I need to use something like Lag and/or Over
However I don't think I'm looking to partition the data and I can only get Lag to work on one row at present!
SELECT Processing_date, LAG (Contaminated, 1, 0) OVER (ORDER BY processing_date ) as item_to_be_checked
Which yields:
+---------------+------------+------------------+
|Processing_date|Contaminated|item_to_be_checked|
+---------------+------------+------------------+
|2000/01/01 | FALSE |FALSE |
|2000/01/02 | TRUE |TRUE |
|2000/01/03 | FALSE |TRUE |
|2000/01/04 | FALSE |FALSE |
|2000/01/05 | FALSE |FALSE |
+---------------+------------+------------------+
Upvotes: 0
Views: 360
Reputation: 37472
You can use the windowed version of max()
. Unfortunately max()
doesn't accept bit
s directly, so some casting to/from integer
s is needed.
SELECT processing_date,
contaminated,
convert(bit, max(convert(integer, contaminated)) OVER (ORDER BY processing_date)) item_to_be_checked
FROM elbat;
Upvotes: 1
Reputation: 4187
So, if your decision if an item has to be rechecked, you might want to get the first conterminated date and then check wverything afterwards:
DECLARE @t TABLE(
Processing_date DATE
,Contaminated BIT
)
INSERT INTO @t VALUES
('2000-01-01', 0)
,('2000-01-02', 1)
,('2000-01-03', 0)
,('2000-01-04', 0)
DECLARE @MinContermDate DATE = (SELECT MIN(Processing_date) FROM @t WHERE Contaminated = 1)
SELECT Processing_date
,CASE WHEN Contaminated = 1 THEN N'TRUE' ELSE N'FALSE' END AS Contaminated
,CASE WHEN t.Processing_date >= @MinContermDate THEN N'TRUE' ELSE N'FALSE' END AS item_to_be_checked
FROM @t t
If you don't want to declare the variable at the beginning, you can put the corresponding query into a CTE and join to it.
Another possibility is UNBOUNDED PRECEDING
:
SELECT Processing_date
,CASE WHEN Contaminated = 1 THEN N'TRUE' ELSE N'FALSE' END AS Contaminated
,CASE WHEN MAX(CASE WHEN Contaminated = 1 THEN 1 ELSE 0 END) OVER (ORDER BY t.Processing_date ROWS UNBOUNDED PRECEDING) = 1 THEN N'TRUE' ELSE N'FALSE' END AS item_to_be_checked
FROM @t t
In this case you don`t need the CTE or the variable.
Upvotes: 1
Reputation: 95554
I would use a windowed COUNT
, to check if there was a previous contamination:
SELECT V.Processing_date,
V.Contaminated,
CONVERT(bit,CASE WHEN COUNT(CASE Contaminated WHEN 1 THEN 1 END) OVER (ORDER BY Processing_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) > 0 THEN 1 ELSE 0 END) AS item_to_be_checked
FROM (VALUES(CONVERT(date,'20000101'),CONVERT(bit,0)),
(CONVERT(date,'20000102'),CONVERT(bit,1)),
(CONVERT(date,'20000103'),CONVERT(bit,0)),
(CONVERT(date,'20000104'),CONVERT(bit,0)))V(Processing_date,Contaminated);
Upvotes: 1