Оператор IF В Пункте ORDER BY Оператора SELECT в Хранимой процедуре SQL Server

Функции, определяемые в цикле продолжают получать доступ к той же переменной i, в то время как ее значение изменяется. В конце цикла все функции указывают на ту же переменную, которая содержит последнее значение в цикле: эффект - то, что сообщило в примере.

, Чтобы оценить i и использовать его значение, общий шаблон должен установить его как значение по умолчанию параметра: значения по умолчанию параметра оценены, когда def оператор выполняется, и таким образом значение переменной цикла замораживается.

следующие работы как ожидалось:

flist = []

for i in xrange(3):
    def func(x, i=i): # the *value* of i is copied in func() environment
        return x * i
    flist.append(func)

for f in flist:
    print f(2)
6
задан John Saunders 19 August 2009 в 22:56
поделиться

7 ответов

ORDER BY
   CASE WHEN @switch = 0 THEN Field1 END,
   CASE WHEN @Switch = 1 THEN Field2 END
15
ответ дан 8 December 2019 в 04:54
поделиться

Один из способов - создать запрос примерно так:

CREATE PROCEDURE [dbo].[CLICK10_GetCP]
    @switch AS BIT
AS
DECLARE
@SQL nvarchar(max)


     SET @SQL N'SELECT
            acct_nbr,
            acct_name
    FROM
            acct
    ORDER BY '

if(@switch)
BEGIN
    @SQL = @SQL + ' acct_nbr '
END
ELSE
BEGIN 
    @SQL = @SQL + ' acct_Name '
END

Exec SP_ExecuteSQL @SQL
3
ответ дан 8 December 2019 в 04:54
поделиться

Грубый способ:

IF @switch = 1
  BEGIN
    SELECT
            acct_nbr,
            acct_name
    FROM
            acct
    ORDER BY acct_nbr
  END
ELSE
  BEGIN
    SELECT
            acct_nbr,
            acct_name
    FROM
            acct
    ORDER BY acct_name
  END

Вы также должны иметь возможность использовать CASE ... КОГДА я думаю:

SELECT
  acct_nbr,
  acct_name
FROM
  acct
ORDER BY
  CASE @switch
    WHEN 1 THEN acct_nbr
    WHEN 0 THEN acct_name
  END
3
ответ дан 8 December 2019 в 04:54
поделиться

Я не совсем уверен Вы можете? В конечном итоге я бы сделал следующее:

CREATE PROCEDURE [dbo].[CLICK10_GetCP]
    @switch AS BIT
AS
    BEGIN
        if @switch
        begin
            SELECT
                    acct_nbr,
                    acct_name
            FROM
                    acct
            ORDER BY 
                    acct_nbr
        end
        else
        begin
            SELECT
                    acct_nbr,
                    acct_name
            FROM
                    acct
            ORDER BY 
                    acct_name
        end
    END
GO
2
ответ дан 8 December 2019 в 04:54
поделиться

Я подумал, что вы можете изменить параметр на int и отсортировать по столбцу с этим порядковым номером:

CREATE PROCEDURE [dbo].[CLICK10_GetCP]
    @ordinal AS INT
AS
    BEGIN
        SELECT
                acct_nbr,
                acct_name
        FROM
                acct
        ORDER BY @Ordinal

    END
GO

Это вызывает приятную ошибку (SQL2005):

Msg 1008, уровень 16 , Состояние 1, строка 4 Элемент SELECT, обозначенный ORDER BY номер 1 содержит переменную как часть выражения, определяющего положение столбца. Только переменные разрешено при заказе по выражению ссылка на имя столбца.

Поиск в Google нашел это решение здесь (SQL 2005 и выше):

CREATE PROCEDURE [dbo].[CLICK10_GetCP]
    @switch AS BIT
AS
    BEGIN
        SELECT
                acct_nbr,
                acct_name
        FROM
                acct
        ORDER BY  CASE
            WHEN @switch = 0 THEN (RANK() OVER (ORDER BY acct_nbr, acct_name))
            WHEN @switch = 1 THEN (RANK() OVER (ORDER BY acct_name, acct_nbr))
         END
GO
1
ответ дан 8 December 2019 в 04:54
поделиться
    SELECT
            acct_nbr,
            acct_name
    FROM
            acct
    ORDER BY case @switch when 1 then acct_name else acct_nbr end
0
ответ дан 8 December 2019 в 04:54
поделиться

Самый лаконичный подход:

CREATE PROCEDURE [dbo].[CLICK10_GetCP]
    @switch AS BIT
AS
    BEGIN
        SELECT
                acct_nbr,
                acct_name
        FROM
                acct
        ORDER BY 
                case @switch
                    when 1 then acct_nbr
                    when 0 then acct_name
                end

    END
GO

Это может привести к плохому плану выполнения для больших таблиц или может не работать вообще, если acc-nbr - это int, а acct-name - varchar.

Заключение двух отдельных запросов в операторы IF / ELSE может работать заметно лучше для больших наборов данных или быть единственным работоспособным подходом, если типы данных двух столбцов различаются.

0
ответ дан 8 December 2019 в 04:54
поделиться