2011-07-12 8 views
1

誰かが何か良いものを考え出すことができれば、私はタイトルを語るよい方法を考えることができませんでした。基本的には、私は多かれ少なかれ完全に再構成されたデータベースからデータを取得し、一度にすべての製品情報をダンプする古いVB6アプリケーションがあります。だから私はいくつかの内部結合を行う必要がありますこれらのテーブルのすべてを一緒に得る。私は基本的な内部結合を行う方法を知っていますが、私は一つの細部に固執しています。各項目に複数のエントリがあるテーブルがいくつかあります。たとえば、CrossReferenceテーブルにアイテムの複数の相互参照番号がある場合や、アイテムが1つしかない場合、またはアイテムがない場合があります。これらを動的に別の列に配置することは可能ですか?そう この:行を列として動的に表示する

Item   CrossReferenceNumber 
XXXXX  crossref1 
XXXXX  crossref2 
XXXXX  crossref3 

は、この(いくつかの他のテーブルと結合した後)になる可能性:

Item BasePart Size CrossReferenceNumber1 CrossReferenceNumber2 CrossReferenceNumber3 
XXXX XXXX  Large crossref1    crossref2    crossref3 

しかし、誰相互参照がない場合、何の相互参照列はないだろう。それが可能なのか、私は夢を見ているのですか?

+1

なぜそれを行うとすれば - それは正規化された考えではなく、おそらくここで目標を再考する必要があります。 –

+1

どのDBMS? SQL Serverの場合は、PIVOT演算子のドキュメントを参照してください。同様の例についてもこの質問を参照してください:http://stackoverflow.com/questions/1343145/tsql-pivot-without-aggregate-function – Kilanash

+0

@Kerrek、私はちょうどそのように見えるデータテーブルが必要です、私はそうではありませんそのようなSQLテーブルを作成します。 VB6アプリは回転して、カラム名とそのカラムに関連付けられた値を表示します。私はそれを維持しなければならないことを書いていませんでした。それは以前は完全に正規化されていない1つの巨大なテーブルなので、以前のようなものに戻しています。私はVB6の開発者ではなく、コードをばかにするような気がしません。 – Nick

答えて

1

Oracle 11gおよびSql Server 2005+には、必要な機能を実現するピボットコマンドが含まれています。

http://www.orafaq.com/wiki/PIVOT

http://msdn.microsoft.com/en-us/library/ms177410.aspx

そうでなければ、これを達成するために、動的SQLステートメントを構築する必要があります。

編集 - ここに行く(SQL Serverのバージョン)。

/* Begin Set up of test data */ 
IF EXISTS (SELECT 1 from sys.tables WHERE name = N'Item') 
    DROP TABLE Item 
GO 

IF EXISTS (SELECT 1 from sys.tables WHERE name = N'CrossReference') 
    DROP TABLE CrossReference 
GO 


CREATE TABLE Item 
(
    Item  varchar(20), 
    BasePart varchar(20), 
    Size  varchar(20) 
); 

CREATE Table CrossReference 
(
    Item  varchar(20), 
    CrossReferenceNumber varchar(20) 
); 

INSERT INTO Item VALUES ('item1', 'b1', 'Large'); 
INSERT INTO Item VALUES ('item2', 'bxx1', 'Large'); 
INSERT INTO Item VALUES ('item3', 'bddf1', 'Small'); 
INSERT INTO Item VALUES ('item4', 'be3f1', 'Small'); 
INSERT INTO Item VALUES ('item5', 'b13vx1', 'Small'); 

INSERT INTO CrossReference VALUES('item1', 'crossRef1') 
INSERT INTO CrossReference VALUES('item1', 'crossRef2') 
INSERT INTO CrossReference VALUES('item1', 'crossRef3') 
INSERT INTO CrossReference VALUES('item1', 'crossRef4') 
INSERT INTO CrossReference VALUES('item2', 'crossRef1') 
INSERT INTO CrossReference VALUES('item2', 'crossRef1') 
INSERT INTO CrossReference VALUES('item3', 'crossRef1') 
INSERT INTO CrossReference VALUES('item4', 'crossRef2') 
INSERT INTO CrossReference VALUES('item5', 'crossRef5') 
INSERT INTO CrossReference VALUES('item5', 'crossRef1') 
INSERT INTO CrossReference VALUES('item5', 'crossRef2') 
INSERT INTO CrossReference VALUES('item5', 'crossRef3') 
/* End of test data setup */ 

/* Begin of actual query */ 
DECLARE @xRefs VARCHAR(2000), 
     @query VARCHAR(8000) 

SELECT @xRefs = STUFF((SELECT DISTINCT '],[' + ltrim(CrossReferenceNumber) 
         FROM CrossReference 
         ORDER BY '],[' + ltrim(CrossReferenceNumber) 
         FOR XML PATH('') 
         ), 1, 2, '') + ']' 

SET @query = 
    'SELECT * 
    FROM Item i 
      INNER JOIN 
      (
       SELECT * 
       FROM 
       (
        SELECT Item, CrossReferenceNumber 
        FROM CrossReference 
       ) t 
       PIVOT (MAX(CrossReferenceNumber) FOR CrossReferenceNumber IN (' + @xRefs + ')) as pvt 

      ) xRefs 
       ON i.Item = xRefs.Item 
    ORDER BY i.Item' 

EXECUTE (@query) 
/* end */ 
+0

ピボットはまだ列を指定する必要があるようです。だから私はCrossReference1、CrossReference2、CrossReference3が結果にあると言わなければならないでしょう、問題は、(理論的に)20の相互参照が存在する可能性があります。あるいは、0が存在する可能性があります。 – Nick

+0

@nick、使用しているdbmsを指定したことはありません。私はあなたがそれがSQLサーバーの場合に使用できる何かを持っています – clyc

+0

申し訳ありません、ms SQL Server 2008 – Nick

関連する問題