使用子查询生成案例陈述

时间:2019-02-27 21:03:40

标签: sql-server tsql

我要完成的工作是相互比较两行,指出行与行之间的差异。每行都有相当多的列,我正尝试使其易于查看,以了解哪些更改了。下面的代码是我的想法,但是我知道这行不通,但这只是一个开始。

SELECT 
        (SELECT  concat('Case WHEN T1.', column_name, ' <> T2.', column_name, ' THEN ''', column_name, ' Changed Values('' + CONVERT(varchar(100), T1.', column_name, ') + '', '' + CONVERT(varchar(100), T2.', column_name, ') + '')'' ELSE '''' END AS ', column_name)
        FROM    information_schema.columns
        WHERE   table_name = 'Table')
    FROM
    (
        SELECT * FROM Table
        WHERE ID = '13'
    ) AS T1 
    JOIN
    (
        SELECT * FROM Table
        WHERE ID = '2006'
    ) AS T2 
        ON T1.CreateTimeStamp = T2.CreateTimeStamp

我有主意,因为在这种情况下可以正常工作,但是我希望这可以成为其他表的可重用代码,而不必每次都键入数十或数百列。

 SELECT 
    Case WHEN T1.R1<> T2.R1 THEN 'Changed Values(' + CONVERT(varchar(100),T1.R1)    + ', ' + CONVERT(varchar(100),T2.R1) + ')' ELSE '' END AS R1,
    Case WHEN T1.R2<> T2.R2 THEN 'Changed Values(' + CONVERT(varchar(100),T1.R2)    + ', ' + CONVERT(varchar(100),T2.R2) + ')' ELSE '' END AS R2
FROM
(
    SELECT * FROM Table
    WHERE ID = '13'
) AS T1 
JOIN
(
    SELECT * FROM Table
    WHERE ID = '2006'
) AS T2 
    ON T1.CreateTimeStamp = T2.CreateTimeStamp

在此示例中,请假设CreateTimeStamp在两行之间始终相等。

1 个答案:

答案 0 :(得分:1)

您需要将整个查询创建为动态SQL。请注意,我正在使用QUOTENAME()来防止SQL注入异常命名的列。我还尝试保持代码格式,因此调试时不会头痛。

DECLARE @SQL NVARCHAR(MAX);

SELECT @SQL = N' SELECT ' + NCHAR(10)
            --Concatenate all columns except ID and CreateTimeStamp
            + STUFF(( SELECT REPLACE( CHAR(9) + ',CASE WHEN T1.<<ColumnName>> <> T2.<<ColumnName>> ' + CHAR(10) 
                        +  CHAR(9) + CHAR(9) + 'THEN ''Changed Values('' + CONVERT(varchar(100),T1.<<ColumnName>>)    + '', '' + CONVERT(varchar(100),T2.<<ColumnName>>) + '')'' ' + CHAR(10) 
                        +  CHAR(9) + CHAR(9) + 'ELSE '''' END AS <<ColumnName>>', '<<ColumnName>>', QUOTENAME(COLUMN_NAME)) + NCHAR(10)
                    FROM INFORMATION_SCHEMA.COLUMNS
                    WHERE TABLE_NAME = 'Table'
                    AND COLUMN_NAME NOT IN( 'ID', 'CreateTimeStamp')
                    FOR XML PATH(''), TYPE).value('./text()[1]', 'nvarchar(max)'), 2, 1, '') + NCHAR(10)
            --Add rest of the query
            + 'FROM Table AS T1 ' + NCHAR(10)
            + 'JOIN Table AS T2 ON T1.CreateTimeStamp = T2.CreateTimeStamp ' + NCHAR(10)
            + 'WHERE ID = @ID1 ' + NCHAR(10)
            + 'AND ID = @ID2;'
--PRINT for debugging purposes
PRINT @SQL;
--Execute the dynamic built code
EXECUTE sp_executesql @SQL, 
                    N'@ID1 int, @ID2 int', 
                    @ID1 = 13, 
                    @ID2 = 2006;

this article上说明了串联方法。