0

私は最近、オラクル クエリのヘルプを得ましたが、それがどのように機能するかをよく理解していないため、自分のデータで機能させることができません。論理的なステップで何が起こっているのか、既存のテーブルの列から実際にどの変数が取得されるのか、その論理を説明できる人はいますか? 読み取り値の表 (列名は日、時間、ボリューム) からデータを選択し、すべての読み取り値に戻ることで、各日の各時間 (つまり、GROUP BY 日、時間) のボリュームの平均読み取り値を見つけようとしています。過去のその時間/日の組み合わせについて(私のデータセットまでさかのぼって)、その平均を書き出します。それが完了すると、同じ列名 (日、時間、ボリューム) を持つ別のテーブルに結果が書き込まれます。1 時間ごとに書き戻す場合を除き、「ボリューム」は過去の 1 日のその時間の平均になります。たとえば、過去のすべての水曜日の午後 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;
4

1 に答える 1

1

これを少し書き直して、(少なくとも私にとっては)より意味のあるものにします。

少しずつ分解すると、CONNECT BYは階層型 (再帰的) クエリです。これは、行を生成するための一般的な「チート」です。この場合、7 は 1 から 7 までの各曜日を表します。

 SELECT LEVEL ds
   FROM DUAL
CONNECT BY LEVEL <= 7

次のものは、午前 0 時から午後 11 時までを表す 0 から 23 までの時間を生成します。これらは、デカルトまたはCROSS JOINの古いスタイルで結合されます。これは、可能なすべての行の組み合わせが返されることを意味します。つまり、1 週間、毎日、1 時間ごとに生成されます。

WITH 句については、SELECT ステートメントに関するドキュメントで説明されています。これは、一般に Common Table Expression (CTE) として知られているか、Oracle では Subquery Factoring Clause として知られています。これにより、サブクエリに名前を割り当て、複数の場所でその単一のサブクエリを参照できます。また、コードをクリーンに保ち、すぐにアクセスできるようにメモリ内に一時テーブルを生成するためにも使用できます。この場合は必須ではありませんが、コードをうまく分離するのに役立ちます。

最後に、+は外部結合に対する Oracle の古い表記法です。それらはほとんど同等ですが、この質問と回答で説明されている非常に小さな違いがいくつかあります。

最初に言ったように、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独自のテーブルの列です。

これが正しいことを行っているかどうかについてはわかりませんが、1 週間ではなく 1 日だけ使用したいということなので、これが正しいかどうかを判断できるのはあなただけですか? HOURSまた、テーブルの列を左に 0 を埋め込んだ文字にする必要があるのも少し奇妙だと思いますがlpad(hrs, 2, '0')、これが正しいかどうかはあなただけが知っています。

これを自分で試して、すべてがどのように連携するかを理解することを強くお勧めします. また、いくつかの基本事項が欠けているようです。教科書を入手するか、インターネットやスタック オーバーフローで調べてみてください。例はたくさんあります。

于 2013-06-01T14:32:34.243 に答える