SQL查询的说明

时间:2013-06-01 14:15:31

标签: oracle

我最近得到了一些oracle查询的帮助,并且不太了解它是如何工作的,因此无法使用它来处理我的数据。是否有人能够解释逻辑步骤中发生的事情的逻辑以及实际从现有表的列中获取的变量?我希望从一个读数表中选择数据(列名是:日,小时,体积),并通过返回所有读数来查找每天每小时的体积平均读数(因此GROUP BY日,小时)对于过去的那个小时/天组合(早在我的数据集中)并写出它的平均值。完成后,它会将结果写入具有相同列名(日,小时,卷)的其他表。除非我每小时回写一次,否则“音量”将是过去一小时的平均值。例如,我想找到过去7点的所有星期三的平均值,并将平均值输出到新的记录。假设使用了这3列,并参考下面的代码,我不确定“小时”与“小时”有什么不同以及t1变量代表什么。任何帮助表示赞赏。

INSERT INTO avg_table (days, hours, avrg)
   WITH xweek
        AS (SELECT ds, LPAD (hrs, 2, '0') hrs
              FROM (    SELECT LEVEL ds
                          FROM DUAL
                    CONNECT BY LEVEL <= 7),
                   (    SELECT LEVEL - 1 hrs
                          FROM DUAL
                    CONNECT BY LEVEL <= 24))
     SELECT t1.ds, t1.hrs, AVG (volume)
       FROM xweek t1, tables t2
      WHERE     t1.ds = TO_CHAR (t2.day(+), 'D')
            AND t1.hrs = t2.hour(+)
   GROUP BY t1.ds, t1.hrs;

1 个答案:

答案 0 :(得分:1)

我会稍微重写这一点,所以它更有意义(至少对我来说)。

为了逐位分解,CONNECT BY是一个分层(递归)查询。这是生成行的常见“作弊”。在这种情况下,7表示一周中的每一天,编号为1到7。

 SELECT LEVEL ds
   FROM DUAL
CONNECT BY LEVEL <= 7

下一个生成小时0到23表示午夜到晚上11点。然后将它们以笛卡尔语或CROSS JOIN的旧样式连接在一起。这意味着返回每个可能的行组合,即它会在一周内每天生成每小时。

SELECT statement的文档中描述了WITH子句,它通常称为公用表表达式(CTE),或者在Oracle子查询因子子句中。这使您可以为子查询指定名称,并在多个位置引用该单个子查询。它还可用于保持代码清洁或在内存中生成临时表以便随时访问。在这种情况下不需要它,但它确实有助于很好地分离代码。

最后,+是Oracle旧外连接的旧表示法。它们大多是等价的,但this question and answer中描述了一些非常小的差异。

正如我在开头所说,我会重写它以符合ANSI标准,因为我发现它更具可读性

insert into avg_table (days, hours, avrg)
with xweek as (
select ds, lpad(hrs, 2, '0') hrs
  from ( select level ds 
           from dual 
        connect by level <= 7 )
 cross join ( select level - 1 hrs 
                from dual 
             connect by level <= 24 )
       )
select t1.ds, t1.hrs, avg(volume)
 from xweek t1
 left outer join tables t2
   on t1.ds = to_char(t2.day, 'd')
  and t1.hrs = t2.hour
group by t1.ds, t1.hrs;

为了进一步详细说明,t1变量代表了CTE week1的别名,因此您不必每次都输入整个内容。 hrs是生成的表达式的别名,因为您明确引用它需要将其称为某种东西。 HOURS是您自己的表格中的一列。

至于这是否做了正确的事情,我不确定,你暗示你只想要一天而不是整个星期,所以只有你能决定这是否正确?我还发现有点奇怪的是,您需要将表格中的HOURS列作为左侧填充0 lpad(hrs, 2, '0')的字符,再次,只有您知道这是否正确。

我强烈建议您自己玩这个,并弄清楚一切如何结合在一起。您似乎也缺少一些基础知识,获取教科书或浏览互联网,或Stack Overflow,这里有很多例子。