不幸的是,我一直坚持这个项目。我需要做的是拿一张包含大约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
然后我可以针对它运行查询:
SELECT *
FROM MyPivot
WHERE KeyID_42 <> KeyID_65
我应该留下这个:
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 :(得分: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;
答案 1 :(得分:0)
这应该可以解决问题,因为它是动态的,你不需要担心字段的数量:
假设:列名将始终采用Field
格式示例数据:
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 '+@whereClauseParam
PRINT(@SQL2);
EXECUTE(@SQL2);
结果:
响应评论“这返回错误:传递给LEFT或SUBSTRING函数的长度参数无效:)”: