Seit Jahrzehnten stehe ich irgendwie auf Kriegsfuß mit SQL. So eine Art Hassliebe. Ich brauche SQL sehr häufig und finde die Syntax trotzdem furchtbar.
JOINs habe ich inzwischen relativ gut verstanden, glaube ich, um die PIVOT-Funktionalität habe ich bisher einen Bogen gemacht.
Doch aktuell war das nicht mehr möglich. Deswegen habe ich mir zahlreiche Ressourcen angeschaut.
Ressourcen/Tutorials
- Pivot in SQL Server
- Simple SQL Tutorial: How to Pivot - DEV Community
- SQL Server PIVOT Operator Explained Clearly By Practical Examples
- SQL Server PIVOT clause with Examples- SQL Server Tutorial
- Verwenden von PIVOT und UNPIVOT - SQL Server | Microsoft Docs
- https://mode.com/sql-tutorial/sql-pivot-table
- Simple Way To Use Pivot In SQL Query - CodeProject
- Microsoft SQL Server Tutorial => Simple PIVOT & UNPIVOT (T-SQL)
- T-SQL Pivot and UnPivot - javatpoint
- Dynamic Pivot Tables in SQL Server
- T-SQL Pivot Tables in SQL Server - Pivot Table Tutorial with Examples
Das oberste Tutorial war für mich das Verständlichste.
Im Grunde ist PIVOT einfach ein 90-Grad-Rotieren von Zeilen in Spalten.
Eigenes Beispielprojekt
Ich habe mir eine neue SQL-Server-Datenbank mit genau zwei Tabellen erstellt, die mein „echtes“ Problem so weit vereinfachen, dass ich damit die Lösung isoliert angehen und lösen kann.
Also quasi das klassische „Minimal, Reproducible Example“.
Struktur
Es gibt eine Kopfdatensatz-Tabelle MyForm
:
CREATE TABLE [MyForm](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](250) NOT NULL,
[DateCreated] [datetime] NOT NULL)
Und es gibt eine Detaildatensatz-Tabelle MyFormField
mit Name-Werte-Paaren:
CREATE TABLE [MyFormField](
[Id] [int] IDENTITY(1,1) NOT NULL,
[MyFormId] [int] NOT NULL,
[FieldName] [nvarchar](250) NOT NULL,
[FieldValue] [nvarchar](max) NULL)
sowie dem Fremdschlüssel:
ALTER TABLE [MyFormField]
WITH CHECK ADD CONSTRAINT [FK_MyFormField_MyForm]
FOREIGN KEY([MyFormId])
REFERENCES [MyForm] ([Id])
Grafisch schaut das so aus:
Daten
Die Tabelle MyForm
ist so gefüllt:
Und die Tabelle MyFormField
ist so gefüllt:
Pivot-Abfrage
SELECT
-- Die Kopfdatensatz-Spalten holen.
FormId, FormName,
-- Die Detaildatensatz-Spalten als Pivots holen.
[Field A], [Field B], [Field C], [Field D]
FROM
(
-- Hier die Kopfdaten und die Detaildatensätze redundant
-- zusammen joinen, damit wir aus das gesamte pivoten können.
SELECT
MyForm.Id AS FormId,
MyForm.Name AS FormName,
MyFormField.FieldName,
MyFormField.FieldValue
FROM
MyForm LEFT OUTER JOIN
MyFormField ON MyForm.Id = MyFormField.MyFormId
) t
PIVOT
(
-- Irgendwas aus der Detailtabelle als Aggregatsfunktion.
MAX(FieldValue)
-- Die Zeilen als Spalten transponieren.
FOR FieldName IN ([Field A], [Field B], [Field C], [Field D])
) as pvt
Ergebnis
Die obige Abfrage hat dann dieses Ergebnis geliefert:
Das kann ich dann entsprechend adaptieren auf mein „echtes“ Projekt.