2011-07-12 82 views
1

我想不出一個好的方式來標題,如果任何人都可以想出更好的東西,請隨意。基本上有一箇舊的VB6應用程序從數據庫中提取數據,我已經或多或少地進行了完全重構,並且一次向用戶提供所有產品信息的轉儲。所以我需要做一些內部連接來將所有這些表結合在一起。我知道如何做基本的內部連接,但我被困在一個細節上。有幾個表格,每個項目有多個條目。例如,CrossReference表可能有一個項目的多個交叉引用號碼,或者它可能只有一個,或者根本沒有。是否有可能將這些動態放置到單獨的列中。所以 這樣的:動態顯示行爲列

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應用程序將旋轉並僅顯示列名和與其相關的值。我沒有寫出我只需要維護的東西。它曾經是一個巨大的完全非規範化的表格,所以我只是發回了一些與之前相似的東西。我不是VB6開發人員,不喜歡弄亂代碼。 – Nick

回答

1

Oracle 11g和Sql Server 2005+都包含一個pivot命令,可以實現您想要的功能。

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服務器2008年 – Nick