Como fazer pedidos condicionais para duas ou mais colunas

10

No MS SQL Server 2005, estou escrevendo uma consulta com classificação condicional e meu problema é que não sei como posso classificar condicional usando duas colunas?

Se eu escrevi um código como este, está funcionando normalmente

select
    *
from 
    table
order by 
    case @pkr 
           when 'kol' then kol
           when 'nci' then nci
    end

Não sei como fazer pedidos condicionais para duas ou mais colunas

select
    *
from 
    table
order by 
    case @pkr
        when 'KOL-NCI' then kol,nci
        when 'kol-MPCI' then kol,mpci
    end

Existe uma idéia para tornar o TSQL dinâmico e usar, sp_executesqlmas ainda estou procurando uma idéia melhor?

adoptilot
fonte
possível duplicata do erro 'Falha na conversão' com a expressão ORDER BY CASE
gbn 27/10/11
Você também pode verificar Faz sentido ter CASE .. END em um ORDER BY? . Embora essa pergunta tenha sido colocada no contexto do PostgreSQL, a maioria dos comentários e considerações da consulta dinâmica WRT vs CASEpode ser aplicável a este caso.
joanolo

Respostas:

12

Admito que nunca tive que fazer isso antes, então houve um pouco de coçar a cabeça envolvido. Tabela de exemplo simples para demonstrar:

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[MyTable]') AND type in (N'U'))
    DROP TABLE [dbo].[MyTable]
GO

CREATE TABLE dbo.MyTable
(
    col1 INT
    , col2 CHAR(1)
)
GO

INSERT dbo.MyTable (col1, col2) VALUES (1, 'A')
INSERT dbo.MyTable (col1, col2) VALUES (1, 'B')
INSERT dbo.MyTable (col1, col2) VALUES (1, 'C')
INSERT dbo.MyTable (col1, col2) VALUES (2, 'A')
INSERT dbo.MyTable (col1, col2) VALUES (2, 'B')
INSERT dbo.MyTable (col1, col2) VALUES (2, 'C')
INSERT dbo.MyTable (col1, col2) VALUES (3, 'A')
INSERT dbo.MyTable (col1, col2) VALUES (3, 'B')
INSERT dbo.MyTable (col1, col2) VALUES (3, 'C')

Usando um parâmetro @SortStyle para diferenciar entre ordens de classificação, @SortStyle = 1 será classificado por col1 ASC, col2 DESCe @ SortStyle = 2 por col2 DESC, col1 ASC.

DECLARE @SortStyle INT
SET @SortStyle = 1

SELECT
    col1
    , col2
FROM
    dbo.MyTable
ORDER BY
    CASE
        WHEN @SortStyle = 1 THEN col1
    END ASC,
    CASE
        WHEN @SortStyle = 1 THEN col2
    END DESC,
    CASE
        WHEN @SortStyle = 2 THEN col2
    END DESC,
    CASE
        WHEN @SortStyle = 2 THEN col1
    END ASC

SET @SortStyle = 2

SELECT
    col1
    , col2
FROM
    dbo.MyTable
ORDER BY
    CASE
        WHEN @SortStyle = 1 THEN col1
    END ASC,
    CASE
        WHEN @SortStyle = 1 THEN col2
    END DESC,
    CASE
        WHEN @SortStyle = 2 THEN col2
    END DESC,
    CASE
        WHEN @SortStyle = 2 THEN col1
    END ASC

Como você ORDER BY um parâmetro abrange o caso mais simples de classificação por apenas 1 coluna.

Mark Storey-Smith
fonte
5

Supondo que você tenha mais casos (adicionei um) e todos os tipos sejam compatíveis,

order by 
    case @pkr
        when 'KOL-NCI' then kol
        when 'kol-MPCI' then kol
        when 'foo-bar' then foo
    end,
    case @pkr
        when 'KOL-NCI' then nci
        when 'kol-MPCI' then mpci
        when 'foo-bar' then bar 
    end

Não é uma classificação com várias colunas: você tem uma classificação primária, seguida por uma classificação secundária. Basta olhar para a caixa de diálogo de classificação no Excel para entender o que quero dizer.

gbn
fonte
1

Com o exemplo que você dá, é simples:

select *
from table
order by kol, case @pkr
                when 'KOL-NCI' then nci
                when 'kol-MPCI' then mpci
              end

Existe uma idéia para tornar o TSQL dinâmico e usar, sp_executesqlmas ainda estou buscando uma melhor idéia.

É sempre bom evitar SQL dinâmico sempre que possível

Jack diz que tenta topanswers.xyz
fonte