0

典型的なレポートスタイルのSQLを実行する際にいくつかの問題があり、経験豊富な人が助けてくれることを期待しています。

私は次のテーブルを持っています

製品

  • 製品番号
  • 商品名
  • 製品カテゴリ

product_defects

  • 製品番号
  • 欠陥日付
  • high_priority
  • med_priority
  • low_priority

カレンダー

  • 日にち

そして、私が望んでいるのは、たとえば、特定の日のproduct_defectにデータが存在しない場合でも、各製品カテゴリに関連する高/中​​/低の欠陥の数を概説するレポートを生成できるようにすることです。 0として返される必要があります。例:

product_category | 日付| 高| ミディアム| 低い

1 2012-10-01 1 5 6

2 2012-10-01 2 4 3

3 2012-10-01 1 5 6

1 2012-10-02 0 0 0

2 2012-10-02 2 4 3

3 2012-10-02 1 5 6

…</p>

私がこれまでに行ったことは次のとおりです。

  • カレンダーと呼ばれるルックアップテーブルを作成します。このテーブルには、数年前/前に戻る一連の日が含まれます。
  • lookup / product_defectsテーブルに直接参加して一連の日付を取得し、欠落している日を0としてマークできるようにしました。
  • COALESCEとSUMを使用して合計を計算し、欠落しているデータを0に変更しました
  • 正確なレポート範囲を取得するために、defect_dateでMIN/MAXを使用しました

誰かが助けてくれることを願って、私はここ数日これに頭を悩ませてきました。

ありがとうございました

4

4 に答える 4

1

製品と日付のすべての組み合わせから始めて、欠陥を結合する必要があります。

select p.product_category, c.date, 
       coalesce(SUM(high_priority), 0) as high_priority,
       coalesce(SUM(med_priority), 0) as med_priority,
       coalesce(SUM(low_priority), 0) as low_priority
from product p cross join
     calendar c left outer join
     product_defects pd
     on pd.product_id = p.product_id and
        pd.date = c.date
group by p.product_category, c.date
order by 2, 1

(注: これはテストされていないため、構文エラーがある可能性があります。)

于 2013-01-15T15:37:43.223 に答える
1

このようなもの。カレンダーの代わりにデュアルを使用したり、カレンダーテーブルを代用したりできます。

たとえば、開始日は 2013 年 1 月 1 日から 2013 年 1 月 15 日までです。

with dates as (select to_date('01/01/2013', 'dd/mm/yyyy') + rownum - 1 dte
                 from dual 
               connect by level <= to_date('15/01/2013', 'dd/mm/yyyy') 
                         - to_date('01/01/2013', 'dd/mm/yyyy') + 1)
select dt.dte, p.product_id, p.product_name, 
       sum(d.high_priority), sum(d.med_priority), sum(d.low_priority)
  from products p
       inner join product_defects d
               on d.product_id = p.product_id
       right outer join dates dt
                     on dt.dte = d.defect_date -- trunc(d.defect_date) if you store with a time element.
 group by dt.dte, p.product_id, p.product_name
 order by dt.dte;
于 2013-01-15T15:44:11.247 に答える
1

したがって、これはサブファクトリ クエリ句 ( cte) を使用して、各日の各カテゴリのすべての欠陥を集計します。この構成を使用して、ロジックをより明確にしました。他にも方法があります。次に、サブクエリがカレンダー テーブルに外部結合されます。

with cte as 
    ( select p.product_category
             , d.defect_date
             , sum(pd.high_priority) as high_priority
             , sum(pd.med_priority) as med_priority
             , sum(pd.low_priority) as low_priority
      from product p
           join product_defect pd
                on (pd.product_id = p.product_id )
     group by p.product_category
             , d.defect_date )
select cte.product_category
       , cal.date 
       , nvl(cte.high_priority, 0) as high_priority
       , nvl(cte.med_priority, 0) as med_priority
       , nvl(cte.low_priority, 0) as low_priority
from calendar cal
     left outer join cte 
        on cal.date = cte.defect_date
order by cte.product_category
       , cal.date 
于 2013-01-15T15:44:57.093 に答える
0

カレンダー テーブルの例のみ。月数を -24 (2 年) から任意の数に増やします - コードをコピーして貼り付けます。

-- 2 years back by date  --
SELECT TRUNC(SYSDATE, 'YEAR') - LEVEL AS mydate
 FROM dual
CONNECT BY LEVEL <= TRUNC(SYSDATE, 'yy') - TRUNC(Add_Months(SYSDATE, -24), 'yy')
/

さらに日付を追加:

-- 2 years back by date and week  --
SELECT mydate
 , TRUNC(mydate, 'iw') wk_starts
 , TRUNC(mydate, 'iw') + 7 - 1/86400 wk_ends
 , TO_NUMBER (TO_CHAR (mydate, 'IW')) ISO_wk#  
FROM
(
SELECT TRUNC(SYSDATE, 'YEAR') - LEVEL AS mydate
  FROM dual
CONNECT BY LEVEL <= TRUNC(SYSDATE, 'yy') - TRUNC(Add_Months(SYSDATE, -24), 'yy')
)
/

テーブルの作成と挿入スクリプトを投稿して、残りの質問に答えるか、sqlfiddle を使用します...

于 2013-01-15T16:23:40.243 に答える