Sql-Server
如果我不知道它將有多少列,如何 PIVOT/UNPIVOT?
我有這個簡單的查詢:
我想列出這樣的內容:
單元 1 \ 板 1 \ 板 2 \ 板 3
單元2\板1\板2
但我不知道一個unidade會有多少個placas。
我試圖像這樣旋轉:
SELECT [undiade], [placa1], [placa2], .. FROM Table1 join table2 bla bla bla PIVOT ( Unidade FOR [unidade] IN ([placa1], [placa2], [placa3]) ) AS P
如果有什麼我無法理解的是如何旋轉。
編輯1:
我試過這個沒有成功:
Select distinct Unidade, substring( ( Select ','+unidade AS [text()] From unidades.Unidades u join t1.Viat v on u.unidade = v.unidade_id where v.parametrizado=0 ORDER BY 1 For XML PATH ('') ), 2, 1000) [Unidades] From unid.unids.unids u
Conversion failed when converting the varchar value 'field' to data type int.
用一些簡單的東西做到了(我真的不擅長程式:
Select main.unidade_id, Left(Main.viaturas,Len(Main.viaturas)-1) As "Viaturas" into #temp From ( Select distinct v2.unidade_id, ( Select v1.placa + ',' AS [text()] From frotas.Viaturas_Temp v1 Where v1.unidade_id = v2.unidade_id ORDER BY v1.unidade_id For XML PATH ('') ) [viaturas] From frotas.Viaturas_Temp v2 ) [Main] select u.unidade, t.viaturas from Unidades.Unidades u join #temp t on u.id=t.unidade_id drop table #temp
正如 Julien 所提到的,動態 sql 將是您的答案。下面是使用 EAV 系統進行旋轉的範例。它確實有助於讀取數據。
DECLARE @Cols NVARCHAR(MAX) DECLARE @Query NVARCHAR(MAX) DECLARE @ClassName NVARCHAR(50) SET @ClassName = 'customer' SELECT @Cols = STUFF((SELECT distinct ',' + QUOTENAME(property_name) FROM Entity_Property ep INNER JOIN Entity e ON ep.eid = e.eid INNER JOIN Class c ON c.cid = e.cid WHERE c.class_name = @ClassName FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') SET @Query = 'SELECT * FROM (SELECT ep.eid, ep.property_name, ep.property_val FROM Entity_Property ep INNER JOIN Entity e ON e.eid = ep.eid INNER JOIN Class c ON c.cid = e.CID WHERE c.class_name = ''' + @ClassName + ''') as src PIVOT ( MAX(Property_val) FOR property_name IN (' + @Cols + ') ) AS piv;' EXEC(@Query)
- 編輯 -
這是將執行您正在尋找的程式碼的程式碼。我使用臨時表作為我的資訊來源,而不是您提供的查詢,因此請隨意使用它而不是#Table。下面的程式碼可以單獨執行以查看輸出的樣子,因此通過一些調整,您可以將其綁定到您的表格。
-- Mimicing what we have for testing purposes CREATE TABLE #Table ( Unidade VARCHAR(100), Placa CHAR(8) ) INSERT INTO #Table (Unidade, Placa) VALUES ('Divisao Administrativa', 'DJL-2937'), ('Instituto de Crimalistica', 'DJL-2690'), ('Instituto de Crimalistica', 'CDV-7883'), ('Instituto de Crimalistica', 'DJP-2304'), ('Instituto Medico Legal', 'DJL-2925'), ('Instituto Medico Legal', 'DJL-2689'), ('Instituto Medico Legal', 'DJL-2851'), ('Instituto Medico Legal', 'CMW-6316') -- Using a temp table to hold a copy of our data with a new column for column headers SELECT Unidade, 'Placa' + CAST(ROW_NUMBER() OVER (PARTITION BY Unidade ORDER BY Placa) AS VARCHAR(10)) AS NewColumnHeader, -- If you have an order for numbering you want to use, add it to the above query and use it here Placa INTO #TableWithNewColumnHeaders -- The 'dirty' way of creating a temp table. FROM #Table -- Now grab what all our new columns will be (Placa1, Placa2, etc) DECLARE @Cols NVARCHAR(MAX) DECLARE @Query NVARCHAR(MAX) SELECT @Cols = STUFF((SELECT distinct ',' + QUOTENAME(NewColumnHeader) FROM #TableWithNewColumnHeaders FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') -- Now we pivot our results SET @Query = 'SELECT p.* FROM (SELECT Unidade, NewColumnHeader, Placa FROM #TableWithNewColumnHeaders) AS SourceQuery PIVOT ( MAX(Placa) FOR NewColumnHeader IN (' + @Cols + ') ) AS p' EXEC(@Query)
這個想法是,我們創建一個新列,它將成為我們的新列標題。這就是讓我們得到我們想要的列名的原因。一旦我們這樣做了,它就是一個簡單的數據透視語句,將標題值轉換為我們的新列名。