我有一个超过 10 列的选择语句。我必须根据日期重复缺少数据的行。 要生成的行应该包含前面行中的数据,这些数据按日期升序排序。 要考虑的日期范围基于 id 的分组。
日期实际上是从 3 月 15 日到 4 月 16 日的范围,但为了示例我只取了有限的行。
例如数据如下图
ID Date Type Code Location
==== ====== === ==== ====
1 15-Mar TG RET X1
1 17-Mar GG CAN S2
1 20-Mar DTR ISS D2
2 14-Apr YT RR F2
2 16-Apr F FC F1
异常输出:
ID Date Type Code Location
=== ==== ==== ==== ======
1 15-Mar TG RET X1
*1 16-Mar TG RET X1*
1 17-Mar GG CAN S2
*1 18-Mar GG CAN S2*
*1 19-Mar GG CAN S2*
1 20-Mar DTR ISS D2
2 14-Apr YT RR F2
*2 15-Apr YT RR F2*
2 16-Apr F FC F1
最佳答案
这是实现所需输出的可能方法的工作示例。我正在使用 Oracle 的 LAST_VALUE
IGNORE NULLS
的解析函数选项和 ORDER BY
条款。
测试数据:
CREATE TABLE so123 (
id NUMBER,
d DATE,
type VARCHAR2(10),
code VARCHAR2(10),
location VARCHAR2(10)
);
INSERT INTO so123 VALUES (1, DATE '2015-05-15', 'TG', 'RET', 'X1');
INSERT INTO so123 VALUES (1, DATE '2015-05-17', 'GG', 'CAN', 'S2');
INSERT INTO so123 VALUES (1, DATE '2015-05-20', 'DTR', 'ISS', 'D2');
INSERT INTO so123 VALUES (2, DATE '2015-04-14', 'YT', 'RR', 'F2');
INSERT INTO so123 VALUES (2, DATE '2015-04-16', 'F', 'FC', 'F1');
COMMIT;
选择本身:
WITH
dmm AS (
SELECT MIN(d) min_d, MAX(d) max_d FROM so123
)
SELECT
NVL(s.id, LAST_VALUE(s.id) IGNORE NULLS OVER (ORDER BY dt.d)) AS id,
dt.d,
NVL(s.type, LAST_VALUE(s.type) IGNORE NULLS OVER (ORDER BY dt.d)) AS type,
NVL(s.code, LAST_VALUE(s.code) IGNORE NULLS OVER (ORDER BY dt.d)) AS code,
NVL(s.location, LAST_VALUE(s.location) IGNORE NULLS OVER (ORDER BY dt.d)) AS location
FROM (
SELECT min_d + level - 1 as d
FROM dmm
CONNECT BY min_d + level - 1 <= max_d
) dt LEFT JOIN so123 s ON (dt.d = s.d)
ORDER BY dt.d
;
输出:
ID D TYPE CODE LOCATION
---------- ---------------- ---------- ---------- ----------
2 14-04-2015 00:00 YT RR F2
2 15-04-2015 00:00 YT RR F2
2 16-04-2015 00:00 F FC F1
2 17-04-2015 00:00 F FC F1
2 18-04-2015 00:00 F FC F1
2 19-04-2015 00:00 F FC F1
2 20-04-2015 00:00 F FC F1
2 21-04-2015 00:00 F FC F1
2 22-04-2015 00:00 F FC F1
2 23-04-2015 00:00 F FC F1
2 24-04-2015 00:00 F FC F1
2 25-04-2015 00:00 F FC F1
2 26-04-2015 00:00 F FC F1
2 27-04-2015 00:00 F FC F1
2 28-04-2015 00:00 F FC F1
2 29-04-2015 00:00 F FC F1
2 30-04-2015 00:00 F FC F1
2 01-05-2015 00:00 F FC F1
2 02-05-2015 00:00 F FC F1
2 03-05-2015 00:00 F FC F1
2 04-05-2015 00:00 F FC F1
2 05-05-2015 00:00 F FC F1
2 06-05-2015 00:00 F FC F1
2 07-05-2015 00:00 F FC F1
2 08-05-2015 00:00 F FC F1
2 09-05-2015 00:00 F FC F1
2 10-05-2015 00:00 F FC F1
2 11-05-2015 00:00 F FC F1
2 12-05-2015 00:00 F FC F1
2 13-05-2015 00:00 F FC F1
2 14-05-2015 00:00 F FC F1
1 15-05-2015 00:00 TG RET X1
1 16-05-2015 00:00 TG RET X1
1 17-05-2015 00:00 GG CAN S2
1 18-05-2015 00:00 GG CAN S2
1 19-05-2015 00:00 GG CAN S2
1 20-05-2015 00:00 DTR ISS D2
37 rows selected
这是如何运作的?我们从源表中生成 MIN 和 MAX 日期之间的所有日期。为此,我们使用 CONNECT BY
使 Oracle 生成记录直到条件 min_d + level - 1 <= max_d
的子句不再持有。
然后,我们获取生成的记录和LEFT JOIN
他们的源表。 LAST_VALUE
来了分析函数的魔力发挥作用。此函数使用指定的顺序搜索表中的最后一个非空值(IGNORE NULLS
选项)并填充缺失的字段。
您可以在此处阅读有关该功能的更多信息:
http://oracle-base.com/articles/misc/first-value-and-last-value-analytic-functions.php
关于sql - Oracle中的Select语句产生重复行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30337449/