SQL Oracle - concatenate sequential strings with filter

| RecordId | foo_id | high_speed |   speed  | DateFrom   |  DateTo     |
------------------------------------------------------------------------
| 666542   |   12   |   60       |   10     | 09/11/2011 |  10/11/2011 |
| 666986   |   13   |   20       |   20     | 11/11/2011 |  11/11/2011 |
| 666996   |   12   |   0        |   0      | 13/11/2011 |  17/11/2011 |
| 755485   |   12   |   0        |   0      | 01/11/2011 |  14/11/2011 |
| 758545   |   12   |   70       |   50     | 15/11/2011 |  26/11/2011 |
| 796956   |   12   |   40       |   40     | 09/11/2011 |  09/11/2011 |
| 799656   |   13   |   25       |   20     | 09/11/2011 | 09/11/2011  |
| 808845   |   12   |   0        |   0      | 15/11/2011 | 15/11/2011  |
| 823323   |   12   |   0        |   0      | 15/11/2011 | 16/11/2011  |
| 823669   |   12   |   0        |   0      | 17/11/2011 | 18/11/2011  |
| 899555   |   12   |   0        |   0      | 18/11/2011 | 19/11/2011  |
| 990990   |   12   |   20       |   10     | 12/11/2011 | 12/11/2011  |

      

Here I want to build a database view that concatenates sequential lines having rate = 0. In this case, DateFrom will be the DateFrom value from the first line, and DateTo will be the DateTo value of the last line. What are the results in the table as follows:

| foo_id | high_speed |    speed  | DateFrom    |    DateTo    |
---------------------------------------------------
|   12   |  60        |     10    |  09/11/2011 |  10/11/2011  |
|   13   |  20        |     20    |  11/11/2011 |  11/11/2011  |
|   12   |  0         |     0     |  13/11/2011 |  14/11/2011  |
|   12   |  70        |     50    |  15/11/2011 |  26/11/2011  |
|   12   |  40        |     40    |  09/11/2011 |  09/11/2011  |
|   13   |  25        |     20    |  09/11/2011 |  09/11/2011  |
|   12   |  0         |     0     |  15/11/2011 |  19/11/2011  |
|   12   |  20        |     10    |  12/11/2011 |  12/11/2011  |

      

To get the result with concatenating sequential strings having rate = 0, I developed a view where a custom sql query looks like this:

select foo_id, high_speed, speed, datefrom, dateto, dateto-datefrom period
  from (
    select recordid, foo_id, high_speed, speed, datefrom, 
      case when tmp = 2 then lead(dateto) over (order by recordid) 
                        else dateto end dateto, tmp 
      from (
        select test.*, case when speed <> 0 then 1 
                       when lag(speed) over (order by recordid) <> 0 then 2
                       when lead(speed) over (order by recordid) <> 0 then 3 
                       end tmp
          from test )
      where tmp is not null)
   where tmp in (1, 2) order by recordid

      

Now I have to apply the same result as for foo_id. To get this result, you need to apply the filter foo_id to the inner nested query. Can I create a view with a parameter? or how can I construct any function that takes one argument that will be compared against the foo_id column. ex -

select foo_id, high_speed, speed, datefrom, dateto, dateto-datefrom period
      from (
        select recordid, foo_id, high_speed, speed, datefrom, 
          case when tmp = 2 then lead(dateto) over (order by recordid) 
                            else dateto end dateto, tmp 
          from (
            select test.*, case when speed <> 0 then 1 
                           when lag(speed) over (order by recordid) <> 0 then 2
                           when lead(speed) over (order by recordid) <> 0 then 3 
                           end tmp
              from test where foo_id=12 )
          where tmp is not null)
       where tmp in (1, 2) order by recordid

      

+2


source to share


1 answer


It has been four years since this question was asked. But Oracle added the MATCH_RECOGNIZE clause in Oracle 12c and it made the solution easier.

SELECT
  foo_id, high_speed, speed,
  NVL(DateFromZ, DateFrom) DateFrom,
  NVL(DateToZ, DateTo) DateTo
FROM test
MATCH_RECOGNIZE (
  ORDER BY RecordId
  MEASURES
    FIRST(zeros.DateFrom) AS DateFromZ,
    FINAL LAST(zeros.DateTo) AS DateToZ,
    COUNT(*) AS cnt
  ALL ROWS PER MATCH WITH UNMATCHED ROWS
  PATTERN (zeros+)
  DEFINE
    zeros AS zeros.speed = 0
)
WHERE speed > 0 OR cnt = 1
ORDER BY RecordId;

      

Output:



+--------+------------+-------+------------+------------+
| FOO_ID | HIGH_SPEED | SPEED |  DATEFROM  |   DATETO   |
+--------+------------+-------+------------+------------+
|     12 |         60 |    10 | 09/11/2011 | 10/11/2011 |
|     13 |         20 |    20 | 11/11/2011 | 11/11/2011 |
|     12 |          0 |     0 | 13/11/2011 | 14/11/2011 |
|     12 |         70 |    50 | 15/11/2011 | 26/11/2011 |
|     12 |         40 |    40 | 09/11/2011 | 09/11/2011 |
|     13 |         25 |    20 | 09/11/2011 | 09/11/2011 |
|     12 |          0 |     0 | 15/11/2011 | 19/11/2011 |
|     12 |         20 |    10 | 12/11/2011 | 12/11/2011 |
+--------+------------+-------+------------+------------+

      

Demo on db & lt;> violin .

+1


source







All Articles