2016-02-26 64 views
1

不幸的是,我一直堅持這個項目的方式。我需要做的是拿一張大約有100個字段的表格,比較兩個記錄,確定哪些字段不匹配。SQL Server數據透視/不透視整個表格(100+個字段)

我能想到的是轉動他們的最好辦法,所以這個:

KeyID Field1 Field2 Field3 Field4 Field5 Field6 
42  Apples Pears Blue  Hills Dog  iPhone 
65  Apples Plums Red  Hills Cat  iPhone 

變成這樣:

FieldName KeyID_42 KeyID_65 
Field1  Apples  Apples 
Field2  Pears  Plums 
Field3  Blue  Red 
Field4  Hills  Hills 
Field5  Dog   Cat 
Field6  iPhone  iPhone 

,然後我可以運行對像的查詢:

我應該留下這個:

FieldName KeyID_42 KeyID_65 
Field2  Pears  Plums 
Field3  Blue  Red 
Field5  Dog   Cat 

但是,對於包含100個左右字段的表格,在PIVOT語句中列出它們中的每一個都不會很漂亮。我可能不得不在稍後的另一張桌子上做這個。

有沒有簡單的方法來實現這一目標?一個不需要單獨列出每個字段?

編輯:

我在這一點上,但越來越多的錯誤是這樣的:Invalid column name 'UpdateTime'.

我正在使用的代碼是這樣的:

DECLARE @colsUnpivot AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @colsUnpivot 
    = stuff((select ','+quotename(C.name) 
      FROM sys.columns c 
      WHERE c.object_id = OBJECT_ID('dbo.tblSQLAdminInventory') 
      --AND C.Name <> 'EffectiveDate' 
      for xml path('')), 1, 1, '') 

set @query 
    = 'select KeyID, ID1, ID2 
    from tblSQLAdminInventory 
    unpivot 
    (
     KeyID 
     for ID1 in ('+ @colsunpivot +') 
    ) u 
    unpivot 
    (
     KeyID 
     for ID2 in ('+ @colsunpivot +') 
    ) u  
    ' 

exec sp_executesql @query; 
+0

沒有列出所有領域,你需要使用'動態sql'去解決你的結果。 SO的幾個例子就是這樣做的。 – sgeddes

+0

Double unpivot不會訣竅。爲什麼不轉光兩次? –

+0

Where子句總是WHERE KeyID_42 <> KeyID_65,或者這也需要動態化嗎? –

回答

0

逆透視只有一次,然後寫如下:

;WITH cte AS (
    -- the query with unpivot but only once 
    -- UNPIVOT(value FOR ID IN (...)) 
) 
SELECT 
    * 
FROM 
    cte AS c1 
    INNER JOIN cte AS c2 ON 
     c2.ID=c1.ID 
WHERE 
    c1.KeyId=42 AND 
    c2.KeyId=65 AND 
    c1.value<>c2.value; 
0

這應該做的伎倆,因爲它是動態的,你不需要擔心的字段數:

假設:列名總是會在格式字段

的樣本數據:

CREATE TABLE temp2 (KeyID INT, Field1 VARCHAR(20), Field2 VARCHAR(20), Field3 VARCHAR(20), Field4 VARCHAR(20), Field5 VARCHAR(20), Field6 VARCHAR(20)); 

INSERT INTO temp2 
VALUES 
     (42, 'Apples', 'Pears', 'Blue', 'Hills', 'Dog', 'iPhone'), 
     (65, 'Apples', 'Plums', 'Red', 'Hills', 'Cat', 'iPhone'); 

查詢:

-- Where clause params 
DECLARE @whereClauseParam VARCHAR(MAX) = '[42] <> [65]' --<-- User will need to determine what the condition will be 

--Get the Fields required for the initial pivot 
DECLARE @Fields VARCHAR(MAX)= ''; 

SELECT @Fields+=QUOTENAME(t.name)+', ' 
FROM sys.columns AS t 
WHERE t.object_id = OBJECT_ID('temp2') 
     AND t.name LIKE 'Field[0-9]%'; 

-- Get the KeyId's with alias added 
DECLARE @keyIDs VARCHAR(MAX)= ''; 

SELECT @keyIDs+=QUOTENAME(t.KeyID)+' AS [KeyID_'+CAST(t.KeyID AS VARCHAR(10))+'], ' 
FROM temp2 AS t; 

-- Get the KeyId's without alias 
DECLARE @keyIDs1 VARCHAR(MAX)= ''; 

SELECT @keyIDs1+=QUOTENAME(t.KeyID)+', ' 
FROM temp2 AS t; 

--Generate Dynamic SQL 
DECLARE @SQL2 VARCHAR(MAX)= 'SELECT Value AS FieldName,'; 

SELECT @SQL2+=SUBSTRING(@keyIDs, 1, LEN(@keyIDs)-1)+' 
FROM 
(SELECT KeyID , Value , FieldName 
FROM 
    (SELECT KeyID,'+SUBSTRING(@Fields, 1, LEN(@Fields)-1)+' 
    FROM temp2) p --<-- you will need to change the name to point to your table 
UNPIVOT 
    (FieldName FOR value IN 
     ('+SUBSTRING(@Fields, 1, LEN(@Fields)-1)+') 
)AS unpvt) AS SourceTable 
PIVOT 
(
MAX(FieldName) 
FOR KeyID IN ('+SUBSTRING(@keyIDs1, 1, LEN(@keyIDs1)-1)+') 
) AS PivotTable 
WHERE '[email protected] 

PRINT(@SQL2); 
EXECUTE(@SQL2); 

結果:

enter image description here

在迴應評論「這將返回錯誤:傳遞給左或子字符串函數無效長度參數:)」:

enter image description here

+0

Kamran joon,這將返回錯誤:無效的長度參數傳遞給左或SUBSTRING函數:) – FLICKER

+0

@ FLICKER你確定你已經正確地複製了代碼。我只是跑了,它運行良好! –

+1

有一個值(小寫v)。它應該是Value(大寫字母V)。由於我的整理,我正在犯錯誤。現在,它的工作。謝謝 – FLICKER