2017-02-17 49 views
1

我使用SQL Server 2012.我有一个名为“Table1”的示例表,其中有七列。SQL Server中多列的动态顺序

 CREATE TABLE TABLE1 
      (
       Field1 INT , 
       Field2 INT , 
       Field3 INT , 
       Field4 INT , 
       Field5 INT , 
       Field6 INT , 
       Field7 INT 
      ) 
      GO 

     INSERT INTO TABLE1 VALUES (1,2,9,5,1,5,85) 
     INSERT INTO TABLE1 VALUES (2,6,8,4,1,4,45) 
     INSERT INTO TABLE1 VALUES (3,5,7,3,5,6,1) 
     INSERT INTO TABLE1 VALUES (4,4,6,1,51,4,1) 
     INSERT INTO TABLE1 VALUES (5,5,5,4,7,2,7) 
     INSERT INTO TABLE1 VALUES (6,5,4,6,4,7,8) 
     INSERT INTO TABLE1 VALUES (7,12,5,3,2,5,3) 
     INSERT INTO TABLE1 VALUES (8,1,6,5,9,5,1) 
     INSERT INTO TABLE1 VALUES (9,1,13,2,1,7,3) 
     INSERT INTO TABLE1 VALUES (10,6,9,3,6,2,6) 
     INSERT INTO TABLE1 VALUES (11,2,1,2,8,7,7) 
     INSERT INTO TABLE1 VALUES (12,7,6,1,3,3,2) 
     INSERT INTO TABLE1 VALUES (13,7,2,6,4,7,1) 
     GO 

我创建了以下存储过程,这个SP能够查询考虑通过列问道订单数据。 我可以通过(ASC或Desc)查询每个列的可能性和顺序。

CREATE Procedure ProceName 
    (
     @OrderByField INT = 1, 
     @OrderDirection INT = 0 -- 0 = Asc , 1 = Desc 
    ) 
    As 
    Begin 
     SELECT 
       * 
     FROM Table1 
     ORDER BY 
       CASE WHEN @OrderDirection=0 AND @OrderByField=1 THEN Field1 END ASC, 
       CASE WHEN @OrderDirection=0 AND @OrderByField=2 THEN Field2 END ASC, 
       CASE WHEN @OrderDirection=0 AND @OrderByField=3 THEN Field3 END ASC, 
       CASE WHEN @OrderDirection=0 AND @OrderByField=4 THEN Field4 END ASC, 
       CASE WHEN @OrderDirection=0 AND @OrderByField=5 THEN Field5 END ASC, 
       CASE WHEN @OrderDirection=0 AND @OrderByField=6 THEN Field6 END ASC, 
       CASE WHEN @OrderDirection=0 AND @OrderByField=7 THEN Field7 END ASC, 

       CASE WHEN @OrderDirection=1 AND @OrderByField=1 THEN Field1 END DESC, 
       CASE WHEN @OrderDirection=1 AND @OrderByField=2 THEN Field2 END DESC, 
       CASE WHEN @OrderDirection=1 AND @OrderByField=3 THEN Field3 END DESC, 
       CASE WHEN @OrderDirection=1 AND @OrderByField=4 THEN Field4 END DESC, 
       CASE WHEN @OrderDirection=1 AND @OrderByField=5 THEN Field5 END DESC, 
       CASE WHEN @OrderDirection=1 AND @OrderByField=6 THEN Field6 END DESC, 
       CASE WHEN @OrderDirection=1 AND @OrderByField=7 THEN Field7 END DESC  End 
    GO 



EXECUTE ProceName @OrderByField=1, @OrderDirection=0 
EXECUTE ProceName @OrderByField=6, @OrderDirection=1 

现在我需要改变这个SP通过一系列列接受多列的顺序。他们可以通过名字或列的顺序。 在这种情况下,我应该能够执行我的SP类似下面的命令:

EXECUTE ProceName @OrderByField='6,7,2', @OrderDirection='0,1,1' 

我怎样才能实现这一目标GOOL 使用该sp_executesql的(动态查询)了呢?

+0

https://sqlperformance.com/2012/08/t-sql-queries/conditional-order-by和https://blogs.sentryone.com/aaronbertrand/sql-variant-use -case/ –

回答

0

那么,你的升序和降序不会影响你的情况,除非你想为每列选择asc和desc。这里是使用最后一列。

DECLARE @OrderByField VARCHAR(64) = '1,3,7' 

DECLARE @DynamicColumns VARCHAR(256) = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@OrderByField,1,'FIELD1'),2,'FIELD2'),3,'FIELD3'),4,'FIELD4'),5,'FIELD5'),6,'FIELD6'),7,'FIELD7') 

DECLARE @OrderDirection INT = 1 
DECLARE @order varchar(4) 
SET @order = CASE WHEN @OrderDirection = 1 THEN 'DESC' ELSE 'ASC' END 

--uncomment this line of code to add the sort to every column which only matters for DESC since ASC is default 
--SET @DynamicColumns = REPLACE(@DynamicColumns,',', ' ' + @order + ',') 

DECLARE @sql VARCHAR(MAX) = (
     'SELECT 
       * 
     FROM Table1 
     ORDER BY ' + @DynamicColumns + ' ' + @order) 

SELECT @sql 

EXEC(@sql) 
+0

我认为试图实现的是为每个列字段指定顺序 – LONG

+0

@Long然后将会有更多的参数,每列一个.... – scsimon

+0

是的...这将是复杂的即使是简单的输入 – LONG

0
CREATE Procedure ProceName 
    (
     @OrderByField VARCHAR(100), 
     @OrderDirection VARCHAR(100), 

    ) 
    As 
    Begin 

    Declare @SQL VARCHAR(MAX) 

    if OBJECT_ID('Example1') is not null 
    begin 
    drop table Example 
    end 

    if OBJECT_ID('Example2') is not null 
    begin 
    drop table Example2 
    end 

    Create table Example1 
    (
    id int identity(1,1), 
    Field varchar(20) 
    ) 

    Create table Example2 
    (
    id int identity(1,1), 
    OrderNumber varchar(10) 
    ) 

    --iterate each element for both @OrderByField and @OrderDirection 
    Declare @separator char(1)=',' 
    Declare @position int = 0 
    Declare @name varchar(20) 
    Set @OrderByField = @OrderByField + @separator 
--------------------------------------------------------------------------- 
     /*iterate each for @OrderByField */ 
--------------------------------------------------------------------------- 

    While CHARINDEX (@separator,@OrderByField,@position) != 0 
    BEGIN 

    SET @name = SUBSTRING (@OrderByField,@position,CHARINDEX (@separator,@OrderByField,@position)[email protected]) 

    SET @SQL = 'Insert into Example1([Field]) Values(' + char(39) + @name + char(39) + ')' 
    EXEC(@SQL) 

    SET @position = CHARINDEX(@separator,@OrderByField,@position)+1 

    END 


--------------------------------------------------------------------------- 
     /*iterate each for @OrderDirection */ 
--------------------------------------------------------------------------- 

    SET @position = 0 --do not forget to reset the position number 

    Set @OrderDirection = @OrderDirection + @separator 

    While CHARINDEX (@separator,@OrderDirection,@position) != 0 
    BEGIN 

    SET @name = SUBSTRING (@OrderDirection,@position,CHARINDEX (@separator,@OrderDirection,@position)[email protected]) 

    SET @SQL = 'Insert into Example2([OrderNumber]) Values(' + char(39) + @name + char(39)+ ')' 
    EXEC(@SQL) 

    SET @position = CHARINDEX(@separator,@OrderDirection,@position)+1 

    END 




Set @name = '' --reset the @name for the use of Cursor 
declare @NewName varchar(500) ='' 


Declare row_cursor CURSOR 
FOR 
select 'Field'+a.Field + ' '+ case when b.OrderNumber = 0 then 'ASC' else 'DESC' end +',' as command 
from Example1 as a 
inner join Example2 as b 
on b.id = a.id 


OPEN row_cursor 
FETCH NEXT FROM row_cursor into @name 

WHILE (@@FETCH_STATUS =0) 
begin 
Set @NewName = @NewName + @name 

FETCH NEXT FROM row_cursor into @name 
end 
close row_cursor 
deallocate row_cursor 

SET @NewName = REVERSE(STUFF(REVERSE(@NewName),1,1,'')) 


SET @SQL = 'Select * From Table1 Order by ' + @NewName 

--Print(@SQL) 
EXEC (@SQL) 

END 
+0

检查是否有效 – LONG

+0

逻辑是创建两个表来存储两个输入数据,使用'CHARINDEX'来存储每个输入的每个元素;从连接结果中选择数据以使用表格光标生成每个对,然后使用动态sql获取最终结果 – LONG

+0

我一直在寻找我们不使用动态查询的方式。 (我怎样才能使用sp_executesql(动态查询)实现这个gool?) –