SELECT Data, COUNT(*)
FROM tbl
WHERE Data BETWEEN SYSDATE-7 AND SYSDATE
GROUP BY Data
ORDER BY Data
1週間で、5つの行を取得する予定です-1営業日ごとに1行。 すべてが機能します。 ユーザーが1日に少なくとも1つのアクションを実行する限り。 テーブルに日付のある単一の行がない場合、結果として結果はありません。 また、レポートの予想される5行の代わりに、4 ...または3 ...またはまったくないことになります。 そして、ユーザーはゼロではあるものの5つを見たいと思っています!
解決策は、データを含むテーブルを、日付をリストする別のテーブルにリンクすることです。 日付をリストすることはできますが、顧客は数か月、明日、希望する年の統合レポートを望んでいました。 繰り返しますが、テーブルを作成するには、すでに月と年がありますか? あまり便利ではなく、面白くない。 しかし、これらのテーブルをその場で「エミュレート」しようとするとどうなりますか? 結局、関数は純粋なSQLでの使用に適したデータセットを返すことができます。 これを行うには、補助タイプが必要です。
CREATE OR REPLACE TYPE TDate_Sequence AS TABLE OF DATE;
/
そして、実際には、関数自体:
CREATE OR REPLACE FUNCTION Generate_Date_Sequence( -- - .
Data_Beg DATE, /* .*/
Data_End DATE, /* .*/
Step CHAR) /* : D - , M - , Y - .*/
RETURN TDate_Sequence
AS
data_curr DATE;
stp CHAR;
Result TDate_Sequence := TDate_Sequence();
BEGIN
stp := UPPER(Step);
IF stp = 'D' THEN
data_curr := TRUNC(Data_Beg, 'DD');
ELSIF stp = 'M' THEN
data_curr := TRUNC(Data_Beg, 'MM');
ELSIF stp = 'Y' THEN
data_curr := TRUNC(Data_Beg, 'YYYY');
END IF;
-- .
WHILE data_curr <= Data_End LOOP
Result.EXTEND;
Result(Result.LAST) := data_curr;
IF stp = 'D' THEN
data_curr := data_curr + 1;
ELSIF stp = 'M' THEN
data_curr := ADD_MONTHS(data_curr, 1);
ELSIF stp = 'Y' THEN
data_curr := ADD_MONTHS(data_curr, 12);
END IF;
END LOOP;
-- .
RETURN Result;
END Generate_Date_Sequence;
/
利用可能なデータを生成されたシーケンスに接続します。
SELECT data_sequence.column_value Data, COUNT(tbl.Data)
FROM TABLE(CAST(Generate_Date_Sequence(SYSDATE-30,SYSDATE,'D') AS TDate_Sequence)) data_sequence, tbl
WHERE tbl.Data(+) = data_sequence.column_value
GROUP BY data_sequence.column_value
ORDER BY data_sequence.column_value
...そして、お客様が希望するゼロを取得します!