2017-02-17 55 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?) –