Sql-Server

如果我不知道它將有多少列,如何 PIVOT/UNPIVOT?

  • January 2, 2020

我有這個簡單的查詢:

我想列出這樣的內容:

單元 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)

這個想法是,我們創建一個新列,它將成為我們的新列標題。這就是讓我們得到我們想要的列名的原因。一旦我們這樣做了,它就是一個簡單的數據透視語句,將標題值轉換為我們的新列名。

引用自:https://dba.stackexchange.com/questions/144006