Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak używać funkcji PIVOT w procedurze przechowywanej SQL Server 2005 Łączenie dwóch widoków

Musisz znać wszystkie możliwe wartości, o które można przestawić. Tak więc trudno jest to zrobić bezpośrednio z T-SQL, chyba że używasz dynamicznego SQL, a to może dość szybko stać się nieprzyjemne. Prawdopodobnie lepiej przekazać wszystkie wiersze z powrotem do warstwy prezentacji lub autora raportu i pozwolić mu obrócić je na boki.

Oto krótki przykład PIVOT, jeśli znasz wcześniej wszystkie wartości UBCategory. Pominąłem ICCUDays, ponieważ wydaje się to raczej nieistotne, chyba że istnieją kolumny, które pochodzą z tego widoku jako część wyniku.

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;

Aby uczynić to bardziej dynamicznym, musiałbyś uzyskać rozdzieloną przecinkami listę wartości DISTINCT UBCategory i zbudować oś w locie. Może to wyglądać tak:

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;

Następnie, aby "wysłać dane do nowej tabeli", możesz po prostu uczynić zapytanie INSERT INTO ... SELECT zamiast prostego SELECT. Oczywiście wydaje się to trochę bezużyteczne, ponieważ aby napisać tę instrukcję insert, musisz znać kolejność kolumn (co nie jest gwarantowane przy tym podejściu) i musisz już wstawić kolumny dla każdej potencjalnej kategorii UBCategory tak czy inaczej, więc wydaje się, że to bardzo kurczak i jajko.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Różnica między lokalnymi i globalnymi tabelami tymczasowymi w SQL Server

  2. Dlaczego w tym scenariuszu potrzebuję części „dopasuj” scalania SQL?

  3. jak sformatować getdate na RRRRMMDDGGmmSS

  4. Visual Studio:ContextSwitchDeadlock

  5. Operacja CRUD z ASP.NET Core MVC, Entity Framework Core i SQL Server