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

Criar uma tabela de estilo Pivot no SQL


Uma maneira muito direta de criar conjuntos aninhados é XML:

--Mockup-table
DECLARE @tbl TABLE([State] VARCHAR(100), Project INT, ClassOfPlant VARCHAR(100),[Description] VARCHAR(100),ProjApprovalDate DATE);
INSERT INTO @tbl VALUES
 ('FL',4139904,'TR','2016 CO161 OA341 SPECIAL SERVICES BLANKET',{d'2016-10-11'})
,('FL',4144128,'TR','WSSD RWB M6 GPON CARD ADDITION TO SUPPORT GROWTH',{d'2016-10-11'})
,('FL',4145813,'OP','BRND-RBB-FTTP-GFLD-CROSSINGS-FISHHAWK RANCH W PH4B',{d'2016-10-11'})
,('FL',4146018,'OP','LKLDN-TMF-GFLD 56 SFU DONOVAN RD ESTATES DESIGN',{d'2016-10-11'});

--A pergunta
SELECT t1.[State] AS [@value]
      ,(
        SELECT t2.ClassOfPlant AS [@value]
              ,(
                SELECT t3.Project AS [@value]
                      ,t3.[Description] AS [@desription]
                      ,t3.ProjApprovalDate AS [@apporval_date]
                FROM @tbl AS t3
                WHERE t3.[State]=t1.[State] AND t3.ClassOfPlant=t2.ClassOfPlant
                FOR XML PATH('project'),TYPE
               )
        FROM @tbl AS t2
        WHERE t1.[State]=t2.[State]
        GROUP BY t2.ClassOfPlant
        FOR XML PATH('plant'),TYPE
       )
FROM @tbl AS t1
GROUP BY t1.[State]
FOR XML PATH('state'),ROOT('root')

O resultado
<root>
  <state value="FL">
    <plant value="OP">
      <project value="4145813" desription="BRND-RBB-FTTP-GFLD-CROSSINGS-FISHHAWK RANCH W PH4B" apporval_date="2016-10-11" />
      <project value="4146018" desription="LKLDN-TMF-GFLD 56 SFU DONOVAN RD ESTATES DESIGN" apporval_date="2016-10-11" />
    </plant>
    <plant value="TR">
      <project value="4139904" desription="2016 CO161 OA341 SPECIAL SERVICES BLANKET" apporval_date="2016-10-11" />
      <project value="4144128" desription="WSSD RWB M6 GPON CARD ADDITION TO SUPPORT GROWTH" apporval_date="2016-10-11" />
    </plant>
  </state>
</root>

ATUALIZAÇÃO


Você pode criar seu resultado em termos de tabela a partir do XML assim
SELECT CASE WHEN nd.value('local-name(.)','nvarchar(max)')=N'state' THEN nd.value('@value','nvarchar(max)') END AS [State]           
      ,CASE WHEN nd.value('local-name(.)','nvarchar(max)')=N'plant' THEN nd.value('@value','nvarchar(max)') END AS [ClassOfPlant] 
      ,CASE WHEN nd.value('local-name(.)','nvarchar(max)')=N'project' THEN nd.value('@value','nvarchar(max)') END AS [Project] 
      ,CASE WHEN nd.value('local-name(.)','nvarchar(max)')=N'project' THEN nd.value('@desription','nvarchar(max)') END AS [Description] 
      ,CASE WHEN nd.value('local-name(.)','nvarchar(max)')=N'project' THEN nd.value('@apporval_date','date') END AS [ProjApprovalDate] 
FROM @xml.nodes('//*[local-name(.)!="root"]') AS A(nd)

O resultado
State   ClassOfPlant    Project          Description    ProjApprovalDate
FL      NULL            NULL             NULL           NULL
NULL    OP              NULL             NULL           NULL
NULL    NULL            4145813          BRND-RBB ...   2016-10-11
NULL    NULL            4146018          LKLDN-TMF...   2016-10-11
NULL    TR              NULL             NULL           NULL
NULL    NULL            4139904          2016 CO16...   2016-10-11
NULL    NULL            4144128          WSSD RWB ...   2016-10-11

Use ISNULL para retornar uma string vazia em vez de um NULL se precisar disso...