2017-02-17 12 views
1

SQL Server 2012を使用しています。私は7つの列を持つ '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' 

私はsp_executesqlを(ダイナミッククエリ)を使用してと、このgool をachiveできますか?

+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その後、各列ごとに1つ多くのパラメータが必要になります.... – 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

ロジックが2つの入力データを格納する2つのテーブルを作成する場合は、それぞれの入力から各要素を格納するために 'CHARINDEX'を使います。結合された結果からデータを選択してテーブルカーソルを使用して各ペアを生成し、次に動的SQLを使用して最終結果を取得します – LONG

+0

私は動的クエリを使用しない方法を探していました。 (どうやってsp_executesql(動的クエリ)を使ってこのgoolを取り除くことができますか?) –

関連する問題