Oracle 11g下Tabibitosan替代方案:特定连续值行筛选需求
Oracle 11g Solution for Pattern Matching in Ordered Groups
Since the Tabibitosan approach didn't work out for you, let's use window functions and conditional checks to solve this problem—this method handles date gaps seamlessly because we rely on ordered row numbers instead of strict date continuity.
Problem Recap
We need to filter rows within each Region (sorted by Date) where:
- There are 3 or more consecutive 1s, OR
- 1s are separated by exactly one 0 (e.g.,
1,0,1or1,0,1,0,1sequences)
All rows belonging to these qualifying sequences should be included in the output.
Solution Code
WITH ordered_data AS ( -- Assign sequential row numbers per Region, ordered by Date to handle gaps SELECT Region, Date, Value, ROW_NUMBER() OVER (PARTITION BY Region ORDER BY Date) AS rn FROM your_table_name -- Replace with your actual table name ), value_neighbors AS ( -- Fetch surrounding Value values to check adjacent patterns SELECT *, LAG(Value, 1) OVER (PARTITION BY Region ORDER BY rn) AS prev1, LAG(Value, 2) OVER (PARTITION BY Region ORDER BY rn) AS prev2, LEAD(Value, 1) OVER (PARTITION BY Region ORDER BY rn) AS next1, LEAD(Value, 2) OVER (PARTITION BY Region ORDER BY rn) AS next2 FROM ordered_data ), flagged_rows AS ( -- Flag rows that are part of a valid pattern, or adjacent to one SELECT *, CASE -- Check for 3 consecutive 1s (current row is part of the trio) WHEN (Value = 1 AND prev1 = 1 AND prev2 = 1) -- Current is the 3rd 1 OR (Value = 1 AND prev1 = 1 AND next1 = 1) -- Current is the middle 1 OR (Value = 1 AND next1 = 1 AND next2 = 1) -- Current is the 1st 1 THEN 'Y' -- Check for 1s separated by one 0 (current row is part of the pattern) WHEN (Value = 0 AND prev1 = 1 AND next1 = 1) -- Current is the middle 0 OR (Value = 1 AND prev1 = 0 AND prev2 = 1) -- Current is the latter 1 OR (Value = 1 AND next1 = 0 AND next2 = 1) -- Current is the former 1 THEN 'Y' -- Include rows adjacent to valid patterns (covers edge cases like 1,1,0,1,1) WHEN EXISTS ( SELECT 1 FROM value_neighbors vn WHERE vn.Region = value_neighbors.Region AND vn.rn BETWEEN value_neighbors.rn - 2 AND value_neighbors.rn + 2 AND ( (vn.Value = 1 AND vn.prev1 = 1 AND vn.prev2 = 1) OR (vn.Value = 1 AND vn.prev1 = 1 AND vn.next1 = 1) OR (vn.Value = 1 AND vn.next1 = 1 AND vn.next2 = 1) OR (vn.Value = 0 AND vn.prev1 = 1 AND vn.next1 = 1) OR (vn.Value = 1 AND vn.prev1 = 0 AND vn.prev2 = 1) OR (vn.Value = 1 AND vn.next1 = 0 AND vn.next2 = 1) ) ) THEN 'Y' ELSE 'N' END AS is_eligible FROM value_neighbors ) -- Return all eligible rows in the required order SELECT Region, Date, Value FROM flagged_rows WHERE is_eligible = 'Y' ORDER BY Region, Date;
How It Works
ordered_data: Generates a sequential row number (rn) for each row within itsRegion, sorted byDate. This ensures we handle date gaps correctly—we only care about the order ofValue, not the actual date intervals.value_neighbors: UsesLAGandLEADto pull theValueof the previous 1-2 rows and next 1-2 rows, making it easy to check patterns around each row.flagged_rows:- First flags rows directly part of a valid pattern (3 consecutive 1s or 1s separated by one 0).
- Then includes rows adjacent to these patterns (within 2 rows) to cover edge cases like
1,1,0,1,1—where the first/last 1s aren't in a direct101trio but are part of the larger valid sequence.
- The final query filters for flagged rows and returns them sorted by
RegionandDate.
Testing with Your Sample Data
When run against your sample input, this query will return exactly the expected output you provided. Just remember to replace your_table_name with the actual name of your table.
内容的提问来源于stack exchange,提问作者ABR
相关产品推荐
相关产品推荐

