Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como usar o PIVOT no procedimento armazenado do SQL Server 2005 unindo duas exibições


Você precisa conhecer todos os valores possíveis para PIVOT. Portanto, é difícil fazer isso diretamente com o T-SQL, a menos que você use SQL dinâmico e isso pode ficar complicado rapidamente. Provavelmente é melhor passar todas as linhas de volta para a camada de apresentação ou para o redator de relatórios e deixá-las virar de lado.

Aqui está um exemplo rápido de PIVOT se você souber todos os valores UBCategory com antecedência. Deixei de fora ICCUdays, pois parece bastante irrelevante, a menos que haja colunas que venham dessa exibição como parte do resultado.
USE tempdb;
GO
SET NOCOUNT ON;
GO

-- who on earth is responsible for your naming scheme?
CREATE TABLE dbo.ICCUEnctrSelectedRevCatsDirCost
(
    Account INT,
    UBCategory VARCHAR(10),
    DirectCost DECIMAL(9,2)
);

INSERT dbo.ICCUEnctrSelectedRevCatsDirCost
    SELECT 1, 'foo', 5.25
    UNION SELECT 1, 'bar', 6.25
    UNION SELECT 1, 'smudge', 8.50
    UNION SELECT 2, 'foo', 9.25
    UNION SELECT 2, 'brap', 2.75;

SELECT Account,[foo],[bar],[smudge],[brap] FROM 
    dbo.ICCUEnctrSelectedRevCatsDirCost
    -- WHERE <something>, I assume ???
PIVOT
(
    MAX(DirectCost)
    FOR UBCategory IN ([foo],[bar],[smudge],[brap])
) AS p;

GO
DROP TABLE dbo.ICCUEnctrSelectedRevCatsDirCost;

Para tornar isso mais dinâmico, você teria que obter a lista separada por vírgulas de valores DISTINCT UBCategory e construir o pivô em tempo real. Então pode ficar assim:
USE tempdb;
GO
SET NOCOUNT ON;
GO

-- who on earth is responsible for your naming scheme?
CREATE TABLE dbo.ICCUEnctrSelectedRevCatsDirCost
(
    Account INT,
    UBCategory VARCHAR(10),
    DirectCost DECIMAL(9,2)
);

INSERT dbo.ICCUEnctrSelectedRevCatsDirCost
    SELECT 1, 'foo', 5.25
    UNION SELECT 1, 'bar', 6.25
    UNION SELECT 1, 'smudge', 8.50
    UNION SELECT 2, 'foo', 9.25
    UNION SELECT 2, 'brap', 2.75
    UNION SELECT 3, 'bingo', 4.00;

DECLARE @sql NVARCHAR(MAX),
    @col NVARCHAR(MAX);

SELECT @col = COALESCE(@col, '') + QUOTENAME(UBCategory) + ','
    FROM 
    (
        SELECT DISTINCT UBCategory
        FROM dbo.ICCUEnctrSelectedRevCatsDirCost
    ) AS x;

SET @col = LEFT(@col, LEN(@col)-1);

SET @sql = N'SELECT Account, $col$ FROM 
    dbo.ICCUEnctrSelectedRevCatsDirCost
    -- WHERE <something>, I assume ???
PIVOT
(
    MAX(DirectCost)
    FOR UBCategory IN ($col$)
) AS p;';

SET @sql = REPLACE(@sql, '$col$', @col);

--EXEC sp_executeSQL @sql;
PRINT @sql;

GO
DROP TABLE dbo.ICCUEnctrSelectedRevCatsDirCost;

Então para "enviar os dados para uma nova tabela" você pode simplesmente fazer a consulta um INSERT INTO ... SELECT ao invés de um SELECT direto. Claro, isso parece meio inútil, porque para escrever essa instrução de inserção, você precisa saber a ordem das colunas (o que não é garantido com essa abordagem) e já deve ter colocado colunas para cada UBCcategory em potencial valor de qualquer maneira, então isso parece muito galinha e ovo.