使用隐含/推断数据连接表
Join tables with Implied / Inferred data
这将是一个简单的联接,除了:Table A 对于所有时间和值都是显式的,但是 Table B 仅在与先前值发生变化时才记录行。在查看 Table B 时,可以轻松推断出缺失的时间和值,但如何将其放入查询中?
A.time 中的数据包含每一分钟和相应的 A.Value。
A.Time...........A.Value
9:00...............3.4
9:01...............5.0
9:02...............5.3
9:03...............5.3
9:04...............5.3
and so on…..
Table B 仅包含 B.value 已从先前值更改的行。
B.Time..............B.Value
9:00...................4
9:01...................4.1
This is blank, but I know it to be 9:02 / 4.1
This is blank, but I know it to be 9:03 / 4.1
9:04....................4.7
and so on…
我需要做一个链接 A.Time 和 B.Value 的查询,但我需要查询来理解 Table B 中缺失的时间应该由 B.value 之前的第一个 B.Time。
最终table应该是
A.Time...............B.Value
9:00...................4
9:01...................4.1
9:02...................4.1
9:03...................4.1
9:04...................4.7
我目前正在为 SQL 服务器写这篇文章,但我也需要一个 Oracle 解决方案
提前致谢;
在Oracle中,你可以LEFT JOIN
得到所有的时间,然后用LAST_VALUE(b.value) IGNORE NULLS...
填空。 (注意:ROWS BETWEEN...
部分与 OVER()
子句中的 ORDER BY
是多余的,但为了更加清晰,我喜欢它。
像这样:
SELECT a.time,
LAST_VALUE (b.VALUE)
IGNORE NULLS
OVER (PARTITION BY NULL
ORDER BY a.time
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM table_a a
LEFT JOIN table_b b ON b.time = a.time
ORDER BY a.time;
这是一个完整的测试数据示例:
with table_a ( time, value ) as
( SELECT '9:00', 3.4 FROM DUAL UNION ALL
SELECT '9:01', 5.0 FROM DUAL UNION ALL
SELECT '9:02', 5.3 FROM DUAL UNION ALL
SELECT '9:03', 5.3 FROM DUAL UNION ALL
SELECT '9:04', 5.3 FROM DUAL ),
table_b ( time, value ) as
( SELECT '9:00', 4 FROM DUAL UNION ALL
SELECT '9:01', 4.1 FROM DUAL UNION ALL
SELECT '9:04', 4.7 FROM DUAL )
SELECT a.time,
LAST_VALUE (b.VALUE)
IGNORE NULLS
OVER (PARTITION BY NULL
ORDER BY a.time
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM table_a a
LEFT JOIN table_b b ON b.time = a.time
ORDER BY a.time;
另一种方法(可能 在 SQL 服务器上工作)是使用 OUTER APPLY
。像这样:
SELECT a.time, b.value
FROM table_a a
OUTER APPLY ( SELECT *
FROM table_b b
WHERE b.time <= a.time
ORDER BY b.time desc
FETCH FIRST 1 ROW ONLY ) b
ORDER BY a.time;
基本上,这会从 table B 中为 table A 中的每一行找到最近的非空值。
SQL*服务器解决方案
这是翻译成 SQL*Server:
的 OUTER APPLY
语法
with table_a ( time, value ) as
( SELECT '9:00', 3.4 UNION ALL
SELECT '9:01', 5.0 UNION ALL
SELECT '9:02', 5.3 UNION ALL
SELECT '9:03', 5.3 UNION ALL
SELECT '9:04', 5.3 ),
table_b ( time, value ) as
( SELECT '9:00', 4 UNION ALL
SELECT '9:01', 4.1 UNION ALL
SELECT '9:04', 4.7 )
SELECT a.time, b.value
FROM table_a a OUTER APPLY (
SELECT * FROM table_b b
WHERE b.time <= a.time
ORDER BY b.time desc
OFFSET 0 ROWS
FETCH NEXT 1 ROWS ONLY ) b
ORDER BY a.time;
这将是一个简单的联接,除了:Table A 对于所有时间和值都是显式的,但是 Table B 仅在与先前值发生变化时才记录行。在查看 Table B 时,可以轻松推断出缺失的时间和值,但如何将其放入查询中?
A.time 中的数据包含每一分钟和相应的 A.Value。
A.Time...........A.Value
9:00...............3.4
9:01...............5.0
9:02...............5.3
9:03...............5.3
9:04...............5.3
and so on…..
Table B 仅包含 B.value 已从先前值更改的行。
B.Time..............B.Value
9:00...................4
9:01...................4.1
This is blank, but I know it to be 9:02 / 4.1
This is blank, but I know it to be 9:03 / 4.1
9:04....................4.7
and so on…
我需要做一个链接 A.Time 和 B.Value 的查询,但我需要查询来理解 Table B 中缺失的时间应该由 B.value 之前的第一个 B.Time。
最终table应该是
A.Time...............B.Value
9:00...................4
9:01...................4.1
9:02...................4.1
9:03...................4.1
9:04...................4.7
我目前正在为 SQL 服务器写这篇文章,但我也需要一个 Oracle 解决方案 提前致谢;
在Oracle中,你可以LEFT JOIN
得到所有的时间,然后用LAST_VALUE(b.value) IGNORE NULLS...
填空。 (注意:ROWS BETWEEN...
部分与 OVER()
子句中的 ORDER BY
是多余的,但为了更加清晰,我喜欢它。
像这样:
SELECT a.time,
LAST_VALUE (b.VALUE)
IGNORE NULLS
OVER (PARTITION BY NULL
ORDER BY a.time
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM table_a a
LEFT JOIN table_b b ON b.time = a.time
ORDER BY a.time;
这是一个完整的测试数据示例:
with table_a ( time, value ) as
( SELECT '9:00', 3.4 FROM DUAL UNION ALL
SELECT '9:01', 5.0 FROM DUAL UNION ALL
SELECT '9:02', 5.3 FROM DUAL UNION ALL
SELECT '9:03', 5.3 FROM DUAL UNION ALL
SELECT '9:04', 5.3 FROM DUAL ),
table_b ( time, value ) as
( SELECT '9:00', 4 FROM DUAL UNION ALL
SELECT '9:01', 4.1 FROM DUAL UNION ALL
SELECT '9:04', 4.7 FROM DUAL )
SELECT a.time,
LAST_VALUE (b.VALUE)
IGNORE NULLS
OVER (PARTITION BY NULL
ORDER BY a.time
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM table_a a
LEFT JOIN table_b b ON b.time = a.time
ORDER BY a.time;
另一种方法(可能 在 SQL 服务器上工作)是使用 OUTER APPLY
。像这样:
SELECT a.time, b.value
FROM table_a a
OUTER APPLY ( SELECT *
FROM table_b b
WHERE b.time <= a.time
ORDER BY b.time desc
FETCH FIRST 1 ROW ONLY ) b
ORDER BY a.time;
基本上,这会从 table B 中为 table A 中的每一行找到最近的非空值。
SQL*服务器解决方案
这是翻译成 SQL*Server:
的OUTER APPLY
语法
with table_a ( time, value ) as
( SELECT '9:00', 3.4 UNION ALL
SELECT '9:01', 5.0 UNION ALL
SELECT '9:02', 5.3 UNION ALL
SELECT '9:03', 5.3 UNION ALL
SELECT '9:04', 5.3 ),
table_b ( time, value ) as
( SELECT '9:00', 4 UNION ALL
SELECT '9:01', 4.1 UNION ALL
SELECT '9:04', 4.7 )
SELECT a.time, b.value
FROM table_a a OUTER APPLY (
SELECT * FROM table_b b
WHERE b.time <= a.time
ORDER BY b.time desc
OFFSET 0 ROWS
FETCH NEXT 1 ROWS ONLY ) b
ORDER BY a.time;