Dynamically select distinct current and previous columns from a sql table

后端 未结 2 1036
盖世英雄少女心
盖世英雄少女心 2021-01-14 12:00

I have a temporary table like so

   Id  |Name    |Status |   Rate |  Method  |ModifiedTime             |ModifiedBy
------------------------------------------         


        
2条回答
  •  孤独总比滥情好
    2021-01-14 12:36

    Ok, I adapted my previous answer but on Dynamic SQL. It's a little crazy but it works (using testTable as table name you can change that just replace 'testTable'):

    DECLARE @query NVARCHAR(max) 
    
    SET @query = 'select item, case item'; 
    
    SELECT @query = @query + Stuff(( SELECT 
    ' when '''+a.NAME+''' then cast(prev'+a.NAME+' as varchar) ' 
    FROM sys.all_columns a JOIN sys.tables t ON 
    t.object_id = a.object_id AND t.NAME = 'testTable' AND a.NAME 
    NOT IN ('id', 
    'Name', 'ModifiedTime', 'ModifiedBy') FOR xml path('') ), 1, 0, 
    ''); 
    
    SET @query = @query + ' end as Before, case item '; 
    
    SELECT @query = @query + Stuff(( SELECT 
                           ' when '''+a.NAME+''' then cast('+a.NAME+' as varchar) ' 
                           FROM sys.all_columns a JOIN sys.tables t ON t.object_id = 
                           a.object_id AND t.NAME = 'testTable' AND a.NAME NOT IN ( 
                    'id', 
                           'Name', 
                           'ModifiedTime', 'ModifiedBy') FOR xml path('') ), 1, 1, 
                    ''); 
    
    SET @query = @query 
                 + ' end as After, ModifiedTime, ModifiedBy from ( select '; 
    
    SELECT @query = @query + Stuff(( SELECT a.NAME +', lag('+ a.NAME + 
                           ') over (partition by Name order by id) prev'+a.NAME+', ' 
                    FROM 
                           sys.all_columns a JOIN sys.tables t ON t.object_id = 
                    a.object_id 
                           AND t.NAME = 'testTable' AND a.NAME NOT IN ('id', 'Name', 
                           'ModifiedTime', 'ModifiedBy') FOR xml path('') ), 1, 0, 
                    ''); 
    
    SET @query = @query 
                 + '  ModifiedBy, ModifiedTime from testTable ) as t1 cross join  (' 
    ; 
    
    SELECT @query = @query + Stuff(( SELECT ' select '''+ a.NAME + 
                    '''as item union all ' 
                           FROM 
                           sys.all_columns a JOIN sys.tables t ON t.object_id = 
                    a.object_id 
                           AND t.NAME = 
                           'testTable' AND a.NAME NOT IN ('id', 'Name', 
                    'ModifiedTime', 
                           'ModifiedBy') FOR xml path('') ), 1, 1, ''); 
    
    SET @query = LEFT(@query, Len(@query) - 10); --get rid of last union all 
    SET @query = @query + ' ) items where '; 
    
    SELECT @query = @query + Stuff(( SELECT ' or (item = '''+ a.NAME +''' and '+ 
                    a.NAME + 
                           ' !=  prev'+ a.NAME +')' FROM sys.all_columns a JOIN 
                    sys.tables 
                           t ON t.object_id = a.object_id AND t.NAME = 'testTable' 
                    AND 
                           a.NAME NOT IN ('id', 'Name', 'ModifiedTime', 'ModifiedBy' 
                    ) FOR 
                           xml 
                           path('') ), 1, 3, ''); 
    
    SET @query = @query + ' order by ModifiedTime'; 
    
    EXECUTE Sp_executesql 
      @query 
    

提交回复
热议问题