我有下表,其中包含燃油价格变化。
-------------------------------
| Date | Fuel | Price |
-------------------------------
| 10.07.2018 | Petrol | 4 |
| 13.07.2018 | Petrol | 5 |
| 15.07.2018 | Petrol | 6 |
| 11.07.2018 | Diesel | 8 |
| 14.07.2018 | Diesel | 10 |
-------------------------------
我需要进行SQL查询以填补白天的空白并显示每日燃油价格的报告。
查询结果:
-------------------------------
| Date | Fuel | Price |
-------------------------------
| 10.07.2018 | Petrol | 5 |
| 11.07.2018 | Petrol | 5 |
| 12.07.2018 | Petrol | 5 |
| 13.07.2018 | Petrol | 4 |
| 14.07.2018 | Petrol | 4 |
| 15.07.2018 | Petrol | 6 |
| 11.07.2018 | Diesel | 8 |
| 12.07.2018 | Diesel | 8 |
| 13.07.2018 | Diesel | 8 |
| 14.07.2018 | Diesel | 10 |
-------------------------------
要获得奖励积分:如果今天运行查询(例如今天= 2018年7月17日),查询还应打印直到今天的所有燃油价格:
Query2结果: Query1结果中的所有行+
-------------------------------
| Date | Fuel | Price |
-------------------------------
| 16.07.2018 | Petrol | 6 |
| 17.07.2018 | Petrol | 6 |
| 15.07.2018 | Diesel | 10 |
| 16.07.2018 | Diesel | 10 |
| 17.07.2018 | Diesel | 10 |
-------------------------------
答案 0 :(得分:3)
对于您的第一个查询,您可以结合使用Lead和分层查询来查找下一行的日期。以下内容可用于大多数版本的Oracle:
WITH your_table AS (SELECT to_date('10/07/2018', 'dd/mm/yyyy') dt, 'Petrol' fuel, 4 price FROM dual UNION ALL
SELECT to_date('13/07/2018', 'dd/mm/yyyy') dt, 'Petrol' fuel, 5 price FROM dual UNION ALL
SELECT to_date('15/07/2018', 'dd/mm/yyyy') dt, 'Petrol' fuel, 6 price FROM dual UNION ALL
SELECT to_date('11/07/2018', 'dd/mm/yyyy') dt, 'Diesel' fuel, 7 price FROM dual UNION ALL
SELECT to_date('14/07/2018', 'dd/mm/yyyy') dt, 'Diesel' fuel, 10 price FROM dual)
SELECT dt -1 + LEVEL dt,
fuel,
price
FROM (SELECT dt,
fuel,
price,
LEAD(dt, 1, dt) OVER (PARTITION BY fuel ORDER BY dt) - dt num_days_to_next_price
FROM your_table)
CONNECT BY PRIOR dt = dt
AND PRIOR fuel = fuel
AND PRIOR sys_guid() IS not NULL
AND LEVEL <= num_days_to_next_price
ORDER BY fuel DESC, dt;
DT FUEL PRICE
----------- ------ ----------
10/07/2018 Petrol 4
11/07/2018 Petrol 4
12/07/2018 Petrol 4
13/07/2018 Petrol 5
14/07/2018 Petrol 5
15/07/2018 Petrol 6
11/07/2018 Diesel 7
12/07/2018 Diesel 7
13/07/2018 Diesel 7
14/07/2018 Diesel 10
在前导分析函数中,我使用可选的第二和第三个参数来设置要预读的行数(1),以及如果我们位于分区的最后一行时要放置的值,只需将其与分区最后一行的日期放在同一日期即可。
第二个查询实际上与第一个查询非常相似,唯一的区别是:
过滤返回的行,以使日期不比您感兴趣的日期高
,而不是为分区(aka组)的最后一行选择默认值dt,而是选择您的特定日期加上1天(我们需要添加多余的日期,因为我们想同时显示开始日期和结束日期;如果不显示,则查询将显示开始日期和前一天到最后一天)。
WITH your_table AS (SELECT to_date('10/07/2018', 'dd/mm/yyyy') dt, 'Petrol' fuel, 4 price FROM dual UNION ALL
SELECT to_date('13/07/2018', 'dd/mm/yyyy') dt, 'Petrol' fuel, 5 price FROM dual UNION ALL
SELECT to_date('15/07/2018', 'dd/mm/yyyy') dt, 'Petrol' fuel, 6 price FROM dual UNION ALL
SELECT to_date('11/07/2018', 'dd/mm/yyyy') dt, 'Diesel' fuel, 7 price FROM dual UNION ALL
SELECT to_date('14/07/2018', 'dd/mm/yyyy') dt, 'Diesel' fuel, 10 price FROM dual)
SELECT dt -1 + LEVEL dt,
fuel,
price
FROM (SELECT dt,
fuel,
COALESCE(price, LAG(price) OVER (PARTITION BY fuel ORDER BY dt)) price,
LEAD(dt, 1, to_date('17/07/2018', 'dd/mm/yyyy') + 1) OVER (PARTITION BY fuel ORDER BY dt) - dt num_days_to_next_price
FROM your_table
WHERE dt <= to_date('17/07/2018', 'dd/mm/yyyy'))
CONNECT BY PRIOR dt = dt
AND PRIOR fuel = fuel
AND PRIOR sys_guid() IS not NULL
AND LEVEL <= num_days_to_next_price
ORDER BY fuel DESC, dt;
DT FUEL PRICE
----------- ------ ----------
10/07/2018 Petrol 4
11/07/2018 Petrol 4
12/07/2018 Petrol 4
13/07/2018 Petrol 5
14/07/2018 Petrol 5
15/07/2018 Petrol 6
16/07/2018 Petrol 6
17/07/2018 Petrol 6
11/07/2018 Diesel 7
12/07/2018 Diesel 7
13/07/2018 Diesel 7
14/07/2018 Diesel 10
15/07/2018 Diesel 10
16/07/2018 Diesel 10
17/07/2018 Diesel 10