SQL Oracle - 将连续行与过滤器结合起来
Posted
技术标签:
【中文标题】SQL Oracle - 将连续行与过滤器结合起来【英文标题】:SQL Oracle - Combining consecutive rows with filter 【发布时间】:2015-06-20 19:33:49 【问题描述】:| 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 |
在这里,我想构建一个数据库视图,它结合了速度 = 0 的连续行。在这种情况下,DateFrom 将是第一行的 DateFrom 值,而 DateTo 将是最后一行的 DateTo 值。结果成表如下:
| 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 |
为了获得结合速度为 0 的连续行的结果,我设计了用户 sql 查询的视图,如下所示:
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
现在,我必须应用与 foo_id 相同的结果。要获得此结果,需要将 foo_id 过滤器应用于内部嵌套查询。是否可以使用参数创建视图?或者我如何设计任何带有一个参数的函数,该参数将与 foo_id 列进行比较。前 -
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
【问题讨论】:
至于您的实际问题,您可能对这个答案感兴趣:***.com/questions/2059299/…。如果您想以正确的方式将0
s 组合成一行(该词表示任意数量的0
s),然后再问一个问题。
【参考方案1】:
问这个问题已经四年了。但是 Oracle 在 Oracle 12c 中添加了MATCH_RECOGNIZE 子句,这使得解决方案更加简单。
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;
输出:
+--------+------------+-------+------------+------------+
| 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 |
+--------+------------+-------+------------+------------+
db<>fiddle 上的演示。
【讨论】:
以上是关于SQL Oracle - 将连续行与过滤器结合起来的主要内容,如果未能解决你的问题,请参考以下文章
Drupal 7 视图 - 如何将上下文过滤器与常规过滤器(使用 OR)结合起来?