1

我想从范围内的表中选择值。像这样的东西:

SELECT
  date_values.date_from,
  date_values.date_to,
  sum(values.value)
FROM values
  inner join date_values on values.id_date = date_values.id
  inner join date_units on date_values.id_unit = date_units.id
WHERE
  date_values.date_from >= '14.1.2012' AND
  date_values.date_to <= '30.1.2012' AND
  date_units.id = 4
GROUP BY
  date_values.date_from,
  date_values.date_to
ORDER BY
  date_values.date_from,
  date_values.date_to;

但是这个查询只给我返回日期范围,任何值在哪里。像这样:

14.01.12    15.01.12    66
15.01.12    16.01.12    4
17.01.12    18.01.12    8
...etc

(这里缺少 16.01.12 到 17.01.12)

但我也想选择缺失值,如下所示:

14.01.12    15.01.12    66
15.01.12    16.01.12    4
16.01.12    17.01.12    0
17.01.12    18.01.12    8
...etc

我不能使用 PL/SQL,如果您能建议更通用的解决方案,我可以将其扩展到小时、月、年;会很棒。

4

1 回答 1

2

我将假设您提供date_fromdate_to. 如果是这样,您可以先生成日期列表,然后加入它以获得剩余的结果。或者,您可以对您的表进行union此查询,就像distinct 这将删除任何额外数据一样。date_valuesunion

如果这是生成日期列表的方式:

 select to_date('14.1.2012','dd.mm.yyyy') + level - 1 as date_from
      , to_date('14.1.2012','dd.mm.yyyy') + level as date_to
   from dual
connect by level <= to_date('30.1.2012','dd.mm.yyyy') 
                  - to_date('14.1.2012','dd.mm.yyyy')

您的查询可能会变成

with the_dates as (
 select to_date('14.1.2012','dd.mm.yyyy') + level - 1 as date_from
      , to_date('14.1.2012','dd.mm.yyyy') + level as date_to
   from dual
connect by level <= to_date('30.1.2012','dd.mm.yyyy') 
                  - to_date('14.1.2012','dd.mm.yyyy')
         )
SELECT
  dv.date_from,
  dv.date_to,
  sum(values.value)
FROM values
  inner join ( select the_dates.date_from, the_dates.date_to, date_values.id
                 from the_dates
                 left outer join date_values
                   on the_dates.date_from = date_values.date_from ) dv
     on values.id_date = dv.id
  inner join date_units on date_values.id_unit = date_units.id
WHERE
  date_units.id = 4
GROUP BY
  dv.date_from,
  dv.date_to
ORDER BY
  dv.date_from,
  dv.date_to;

with语法称为子查询分解,在这种情况下并不真正需要,但它使代码更清晰。

我还假设其中的datedate_values是日期。当您进行字符串比较时,这并不明显。您应始终在适用的情况下显式转换为日期,并且应始终将日期存储为日期。从长远来看,它可以节省很多麻烦,因为输入错误或比较错误是不可能的。

于 2012-06-08T09:41:26.340 回答