You do not mention how this name is used, so I assume that you want this to be done by name. I also assume that when you talk about "consecutive", what do you mean in order of dates and not in order of id. Finally, I also assume that you would also exclude 5 zeros per line, 6 zeros per line, etc.
There may be an easier way, but this should work:
;WITH Transitions_To_CTE AS ( SELECT T1.id, T1.name, T1.date, T1.value FROM My_Table T1 LEFT OUTER JOIN My_Table T2 ON T2.name = T1.name AND T2.date < T1.date AND T2.value <> 0 LEFT OUTER JOIN My_Table T3 ON T3.name = T1.name AND T3.date > COALESCE(T2.date, '1900-01-01') AND T3.date < T1.date WHERE T1.value = 0 AND T3.id IS NULL ), Transitions_From_CTE AS ( SELECT T1.id, T1.name, T1.date, T1.value FROM My_Table T1 LEFT OUTER JOIN My_Table T2 ON T2.name = T1.name AND T2.date > T1.date AND T2.value <> 0 LEFT OUTER JOIN My_Table T3 ON T3.name = T1.name AND T3.date < COALESCE(T2.date, '9999-12-31') AND T3.date > T1.date WHERE T1.value = 0 AND T3.id IS NULL ), Range_Exclusions AS ( SELECT S.name, S.date AS start_date, E.date AS end_date FROM Transitions_To_CTE S INNER JOIN Transitions_From_CTE E ON E.name = S.name AND E.date > S.date LEFT OUTER JOIN Transitions_From_CTE E2 ON E2.name = S.name AND E2.date > S.date AND E2.date < E.date WHERE E2.id IS NULL AND (SELECT COUNT(*) FROM dbo.My_Table T WHERE T.name = S.name AND T.date BETWEEN S.date AND E.date) >= 4 ) SELECT T.id, T.name, T.date, T.value FROM dbo.My_Table T WHERE NOT EXISTS (SELECT * FROM Range_Exclusions RE WHERE RE.name = T.name AND T.date BETWEEN RE.start_date AND RE.end_date)
Tom h source share