2012-02-29 1 views
0

OUTER JOINを使用して行に格納された値を取得し、列として表示します。値がない場合は、列にNULLを表示します。行をインデックス付きビューで列に変換する方法はありますか?

ソーステーブル:

Id|Name|Value 
01|ABCG|,,,,, 
01|ZXCB|..... 
02|GHJK|;;;;; 

ビュー:

Id|ABCG|ZXCB|GHJK 
01|,,,,|....|NULL 
02|NULL|NULL|;;;; 

クエリは次のようになります。

SELECT DISTINCT 
    b.Id, 
    bABCG.Value AS "ABCG" 
    bZXCB.Value AS "ZXCB" 
    bGHJK.Value AS "GHJK" 
FROM 
    Bars b 
    LEFT JOIN Bars bABCG ON b.Id = bABCG.Id and b.Name = 'ABCG' 
    LEFT JOIN Bars bZXCB ON b.Id = bZXCB.Id and b.Name = 'ZXCB' 
    LEFT JOIN Bars bGHJK ON b.Id = bGHJK.Id and b.Name = 'GHJK' 

それがインデックス付きビューでは許可されていないので、私はJOINをLEFTを削除したいです。私はそれを内部SELECTで置き換えようとしましたが、内部SELECTもUNIONには許可されていません。私はNULLを表示したいのでINNER JOINは使用できません。私は何を使うべきですか?

+0

あなたは 'FROM bars b、bars b1、bars b2 where(b.id = b2.idとb.name = 'asdfa')と(b.id = b2.idとb.name = 'sdaf').... ' –

+0

はい、これはnullを返しません。 – Pol

+0

ヒント:特定のメソッドがインデックス付きビューで許可されていないという制限に遭遇している場合、同じ結果セットを生成する他のフォームも許可されない可能性が高いです。あなたは、あなたが描いているシェイプでインデックス付きのビューを作成することはできません。 –

答えて

1

あなたが行うことができるとしている最高の内側のマッチを取得するために結合を使用ですが編成されているかどうかはわかりません、値を集計を追加する必要がありますその後、左の結合と結合し、それをフィルタリングしてnullのみを戻します。これはおそらくあなたの問題を解決しません。

システムの詳細はわかりませんが、パフォーマンスの問題を処理していると仮定しています。そのため、インデックス付きのビューを使用する必要があります。いくつかの選択肢がありますが、私は以下が最も適切だと思います。

これはDW用であるとコメントしましたので、あなたのシステムは書き込みよりも読み込みに集中しており、ETLプロセスによってデータがスケジュールに読み込まれると仮定します。この種の高読取り/低書込み*状況では、このビューを「実現」することをお勧めします。これは、ETLプロセスの実行時に、左ジョインを含む最初のselect文で表を生成することを意味します。ヒットを書き込みに当てると、すべての読み込みはインデックス付きビューのパフォーマンスと同じになります(インデックス付きビューで実行するのと同じことを行います。ただし、行単位ではなくバッチ式で行います)。 )。ソースDBとDWが同じインスタンスにある場合、これは索引付きビューb/cよりも優れた選択です。ソースシステムのパフォーマンスに影響を与えません(索引付きビューは挿入を遅くします)。これは、索引付けされたビューと同じ概念です。選択を高速化するために挿入時にパフォーマンス・ヒットを取得するためです。

は、以下の結論を出す前に、私はこのパスダウンしてきた:

インデックス付きビューは、全体のソリューションよりもソリューションの一部である可能性が高いです。

*私はあなた以上の「高読み出し/ローライト」も「高い読み取り/予定の書き込み」と考えることができたとき

+0

申し訳ありませんが、私はそのコメントに正確ではありませんでした。私のシステムはDW用のデータの**ソース**です。この索引ビューは、DWが事前計算されたデータを探すための単一の場所として意味されていました。データは私のシステムからDWで約5時間間隔で読み込まれます。私はDWを変更することはできません。 – Pol

+0

あなたのPoVについて考えると、私はこれを通常のビューであると見なします... – Pol

+0

ETLがソースシステムではなく、5時間ごとに1回のパフォーマンスでヒットするのは理にかなっていると思います。ここでは定期的なビューが適切と思われます。 –

0
SELECT DISTINCT 
    b.Id, 
    (Select bABCG.Value from Bars bABCG where b.Name = 'ABCG') AS "ABCG" 
    ... 
FROM 
    Bars b 

あなたは私はあなたのデータは

+0

これは私の最初の試みでした。しかし、質問に書いたように、内部SELECT(サブクエリ)は、MSSQLでインデックス付きビューを作成するためには許可されていません(「1つ以上のサブクエリが含まれているためビューを作成できません。あるいは、このビューのインデックスを作成しないことを検討してください。 – Pol

+0

私はあなたが次にできるとは思わない!なんらかの種類の左結合を使用しない限り、「NULL」は表示されません。別のトピックでは、なぜあなたはビューのインデックスを作成する必要があるのですか?あなたがそうした時にビューのデータをDBに保存することを知っていますか?あなたは基本的に既に持っているデータのコピーを持っていますか? – Diego

+0

これはデータウェアハウスのシナリオなので、インデックス付きのビューを使用すると合理的ですと思います。 – Pol

2

あなた似たような実際のテーブルを使用して実装することができるかもしれません内部データを維持するために、結果を格納するため、および基本表に対してトリガーのセットを使用します。

I は、インデックスビューを作成するときにSQL Serverが(実際の実装ではないにしても)これが何であるかを示しています。ただし、インデックス付きビューのルールを調べると、のテーブルはinserteddeletedのテーブルを使用する必要があります。また、基本テーブルをスキャンしてメンテナンスを実行する必要はありません。ビューは深刻なパフォーマンスペナルティを課すでしょう。

上記の例では、ビュー内にMAX(column)列を維持するための挿入トリガーを簡単に書き込むことができますが、削除はより問題になります。現在の最大値を削除する場合は、テーブルをスキャンして新しい最大値を決定します。多くの他の制限については、トリガーを手作業で記述してみてください。ほとんどの場合、ベーステーブルをスキャンする必要があります。

これらのトリガーがメンテナンスを効率的に行うことができますが、挿入/更新/削除シナリオのすべてを慎重に検討し、トリガー実際にこのデータを忠実に維持する - 例えばidを更新する場合は、更新、挿入、および削除を混在して実行する必要があります。

関連する問題