2017-03-02 8 views
1

私は、毎日、不具合を示すアイテムをリストする履歴データがあると仮定します。アイテムはこのリストに出入りする。 I.E.-Oracle 12Cトレンディングの行の追加

TABLE NAME: ITEMS_WITH_DEFECTS 

DAY  | ITEMID 
------------------- 
01-JAN-16 | A 
01-JAN-16 | D 
02-JAN-16 | B 
02-JAN-16 | D 
03-JAN-16 | A 
03-JAN-16 | C 
04-JAN-17 | A 
04-JAN-17 | D 

私は、新しい下落しているしている、と引き継がれてきたどのように多くの項目、前日に毎日の相対のために示したデータソースを構築したいと思います。それは私の履歴データソースから任意の情報を失うことなくこれを行うにはしたいと思いますので、私の所望の出力は次のようになります。

TABLE NAME: ITEM_DEFECT_TRENDS 

DAY  | ITEMID | DEFECT | TREND 
------------------------------------ 
01-JAN-16 | A  | y  | New 
01-JAN-16 | B  | n  | (null) 
01-JAN-16 | C  | n  | (null) 
01-JAN-16 | D  | y  | New 
02-JAN-16 | A  | n  | Dropped 
02-JAN-16 | B  | y  | New 
02-JAN-16 | C  | n  | (null) 
02-JAN-16 | D  | y  | Carryover 
03-JAN-16 | A  | y  | New 
03-JAN-16 | B  | n  | Dropped 
03-JAN-16 | C  | y  | New 
03-JAN-16 | D  | n  | Dropped 
04-JAN-16 | A  | y  | Carryover 
04-JAN-16 | B  | n  | (null) 
04-JAN-16 | C  | n  | Dropped 
04-JAN-16 | D  | y  | New 

私はTREND列を生成する方法を知っているが、私は、行を追加する方法がわかりませんまたはDEFECT列を出力に追加します。

SQLまたはPL SQLでこれを行うことはできますか?

このようなデータをモデル化する理由は、データベースには約12,000個の可能なアイテムの大きなリストが含まれていますが、一度に500個ほどのアイテムしか表示されないためです。可能なすべてのアイテムに対して考慮する必要があるアイテムだけで、これをスコープするとメモリがより効率的になります。

+0

SQLで十分です。 Eも表示しなければならないので、すべての 'itemid'(" list "はすべての' itemid'を持つテーブル、理想的にはプライマリキーまたはユニークでないヌルキーを意味します)のリストが必要ですあなたの '欠陥'テーブルの欠陥。 (そうでなければ、あなたの要件はあまり論理的ではありません)。また、これを表示する期間を指定する必要があります。ある日付に 'defect'テーブルに行がない場合は、その日付に欠陥がないことを意味します - 正しい?最後に、レポートの最初の日を「指示する」と、すべてのアイテムが「前の日付に不具合を起こさなかった」とみなされますか? – mathguy

+0

1月1日にAさんがNewを表示するので、最後の質問をします。 12月31日にもそれに欠陥がなかったことをどのように知っていますか?すべてが自己完結型でなければならない場合、世界は1月1日にのみ生まれたので、それは「新」です。それはあなたが取る必要があるポジションですか? – mathguy

+0

速い応答に感謝します。私は欠陥の歴史についてさらに詳しく述べなければならない:それは日々更新されるsysdateで終わる14日間の歴史だ。すべての可能なアイテムID(Eを含む)のセットのうち、通常、一度に表示されるのは約500個で、決して表示されないものは11,500個です。トレンディングの時間枠は入力の時間枠と一致していなければならず、すべての項目は履歴のmin(日)前に不具合が発生していないとみなされます。トレンディングは、可能なセットのアイテムの非常に小さなサブセットにしか適用されないため、出力に絶対必要なアイテムを使用したいだけです。それは理にかなっていますか? –

答えて

1

はい、私はあなたがSQLでこれを行うことができると思います。

select d.day, i.itemid, 
     (case when id.itemid is not null then 'y' else 'n' end) as defect, 
     (case when id.itemid is null and 
        lag(id.itemid) over (partition by i.itemid order by d.day) is null 
      then 'New' 
      when id.itemid is not null and 
        lag(id.itemid) over (partition by i.itemid order by d.day) is not null 
      then 'CarryOver' 
      when lag(id.itemid) over (partition by i.itemid order by d.day) is not null 
      then 'Dropped' 
     end) as trend 
from (select distinct day from items_with_defects) d cross join 
    (select distinct itemid from items_with_defects) i left join 
    items_with_defects id 
    on id.day = d.day and id.itemid = i.itemid; 

アイデアがcross joinを使用してすべての行を生成することです - あなたがそのあなたの日やアイテムの人口を得るための他の方法を持っている場合それを使用してください。

次にleft join一致を確認する元のデータ。 defect列は簡単です。私はtrend列ロジックは正しいと思いますが、質問で完全に説明していません。

+0

これはおそらく不十分です。まずデータの密度を上げる必要があります。商品に欠陥がない日があるかもしれません。現在のクエリでは、その日は出力に現れません。 – mathguy

+0

ゴードン、ありがとう!私は2016年5月からSQLを使用していて、クロスジョインについては知らなかった。トレンディングのロジックは問題ありません。現在の日付では新しいものを意味しますが、以前のものではありません。キャリーオーバーは両方の日を意味し、Droppedは前日を意味しますが現在は意味しません。 @mathguyヒストリテーブルを作成するプロシージャでは、1日のエントリと説明する場合の(null)が1つずつ表示されます。毎日少なくとも1つのレコードが確実に存在します。 –

関連する問題