2017-02-17 7 views
1

Я использую SQL Server 2012. У меня есть таблица с таблицей «Таблица1» с семью столбцами.Динамический порядок по нескольким столбцам в 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 

Я создал ниже хранимую процедуру, этот СП способен запрашивать данные с учетом заданного порядка по столбцу. Я могу запросить таблицу с каждой возможностью одного столбца и порядка (по 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' 

Как я могу achive этого GOOL с с использованием sp_executesql (Dynamic Query)?

+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

Я искал способ, которым мы не используем Dynamic Query. (Как я могу достичь этого gool без использования sp_executesql (Dynamic Query)?) –

Смежные вопросы