带有重复元素的动态SQL查询

时间:2016-11-14 11:30:05

标签: sql sql-server sql-server-2008

我正在尝试使用动态sql构建一个查询,如下所示, 'select dense_rank()over(按column1 order by column1分区),        dense_rank()over(按column1分区,column2按column2排序),        来自tablename'的dense_rank()over(按column1,column2,column3 order column3分区) 我已经使用STUFF来构建查询但是只能用一列创建查询而不能重复列,即'column by column1,column2'。 如何使用STUFF实现这一点还是有其他方法可以做到这一点?

3 个答案:

答案 0 :(得分:1)

Declare @col_name varchar(100)
Declare @colnm varchar(max)
Declare @multicol int
Declare @sqlstr varchar(max)
Declare Cur_1 cursor 
for
Select name 
from sys.columns 
where object_id=object_id('tablename')
order by name

OPEN Cur_1  

FETCH NEXT FROM Cur_1   
INTO  @col_name
set @colnm=''
set @multicol=0
WHILE @@FETCH_STATUS = 0  
BEGIN  
    if @multicol=1 
        begin
            set @colnm=@colnm + ',' + @col_name
        end
    else
        begin
            set @colnm= @colnm+ @col_name
        end
    if @multicol=0
        begin
            set @sqlstr='Select dense_rank () over(partition by ' + @colnm  +  ' order by ' + @colnm + '),'
        end
    else
        begin
            set @sqlstr=@sqlstr + char(13) + char(10) + 'dense_rank () over(partition by ' + @colnm  +  ' order by ' + @colnm + '),' 
        end
    FETCH NEXT FROM Cur_1   
    INTO @col_name 
    set @multicol=1 
END   
CLOSE Cur_1;  
DEALLOCATE Cur_1;  

set @sqlstr=left(@sqlstr,len(@sqlstr)-1) + + char(13) + char(10) + 'from tablename'
print @sqlstr

答案 1 :(得分:1)

您可以使用两个连接字符串的查询来完成此操作。一个外部构建列列表,一个内部构建分区依据的列列表。

样本表:

create table T(C1 int, C2 int, C3 int);

代码:

declare @SQL nvarchar(max);

with C as
(
  select C.name,
         -- Use order by to control order of columns
         row_number() over(order by C.column_id) as rn
  from sys.columns as C
  where object_id = object_id('T') -- Specify the name of the table
                                   -- Optionally filter out any columns that
                                   -- should not be included
)
select @SQL = 'select '+
              stuff((
                    select ',dense_rank() over(partition by '+
                           stuff((
                                 select ','+c2.name
                                 from C as C2
                                 where C2.rn <= C.rn  
                                 order by C2.rn
                                 for xml path(''), type
                                 ).value('text()[1]', 'nvarchar(max)'), 1, 1, '') +
                           ' order by '+C.name+')'
                    from C
                    for xml path(''), type
                    ).value('text()[1]', 'nvarchar(max)'), 1, 1,'')+
              ' from T';

print @SQL;
--exec (@SQL);

结果:

select dense_rank() over(partition by C3 order by C3),
       dense_rank() over(partition by C3,C2 order by C2),
       dense_rank() over(partition by C3,C2,C1 order by C1) 
from T

注意:STUFF (Transact-SQL)不会连接字符串。它用于将一个字符串插入另一个字符串。在上面的代码中,stuff用于通过将空字符串插入第一个位置并覆盖1个字符来删除连接字符串中的前导逗号。实际的连接由for xml完成。

答案 2 :(得分:1)

Declare @QueryString Varchar(Max)
Declare @TblNm Varchar(100)
Set @TblNm='[dbo].[SampleTable]'
Set @QueryString=    
        (
            Select ',dense_rank () over(partition by '+ ColNm + ' Order by [' + name + '])' + char(10)  AS [text()]
            From 
                (
                    SELECT name,ColNm = STUFF(
                                            (
                                                SELECT ',[' + name + ']'
                                                FROM sys.columns
                                                where object_id=object_id(@TblNm) and  column_id<=Tbl1.column_id
                                                FOR XML PATH ('')
                                            ), 1, 1, ''
                                        ) 
                    FROM sys.columns Tbl1
                    where object_id=object_id(@TblNm) 
                ) ColDtl
            For XML PATH ('')
        )
Set @QueryString='Select '
                    + substring(@QueryString,2,len(@QueryString))
                    + ' from ' + @TblNm
Select @QueryString as ExecString
--Exec (@QueryString)