查询以填充记录SQL之间的空白(数据)

时间:2018-07-19 09:54:42

标签: sql oracle

我有下表,其中包含燃油价格变化。

-------------------------------
|    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    |
-------------------------------

1 个答案:

答案 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),以及如果我们位于分区的最后一行时要放置的值,只需将其与分区最后一行的日期放在同一日期即可。

第二个查询实际上与第一个查询非常相似,唯一的区别是:

  • 过滤返回的行,以使日期不比您感兴趣的日期高

  • 在Lead函数中,选择
  • ,而不是为分区(a​​ka组)的最后一行选择默认值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