Voici la solution que je promis:
EDIT: J'ai modifié ma réponse pour répondre addit questions ionales par le PO.
Quelques choses à noter:
- La fonction STUFF: Ceci est utilisé pour convertir la chaîne XML en une chaîne régulière (et pour enlever la première virgule)
- Group By (I a volé ce billet depuis OMG Ponies): Vous devez faire ceci pour vous assurer que vous n'avez pas de dates en double
- Assurez-vous qu'il n'y a pas trop de dates dans la table avant d'exécuter ceci. Trop de colonnes peuvent être un problème
- NVARCHAR: J'ai utilisé ceci à la place de VARCHAR pour la variable @sql car sp_ExecuteSQL l'exige.
- CONVERT (VARCHAR, DateColumn, 101): Je l'ai fait parce que si vous ne convertissez pas la date en chaîne, cela ne marchera pas. 101 résultats dans ce: mm/jj/aaaa mais vous pouvez utiliser tout ce dont vous avez besoin (assurez-vous que le 2 fois il est utilisé dans ce script correspond)
- Pour que cela fonctionne pour plusieurs colonnes, vous devez d'abord utiliser UNPIVOT et convertir toutes les colonnes au même type de données (plus d'informations sous le code)
- Il est important de noter que pour concaténer des chaînes, elles doivent être du même type de données, avec la même taille (dans mon cas, elles sont toutes les deux NVARCHAR (MAX))
Lire this page pour plus d'informations sur la conversion de dates en chaînes.
Cela dit, voici le code:
-- table with multiple columns
CREATE TABLE #TBL (
NameColumn VARCHAR(10),
PriorityColumn INT,
AnotherColumn FLOAT,
DateColumn DATETIME
)
-- Insert the test data
INSERT INTO #TBL VALUES ('a', 1, 7.2, '1/1/2000')
INSERT INTO #TBL VALUES ('a', 2, 8.9, '1/2/2000')
INSERT INTO #TBL VALUES ('a', 2, 53.2, '1/3/2000')
INSERT INTO #TBL VALUES ('a', 3, 9.12, '1/4/2000')
INSERT INTO #TBL VALUES ('b', 2, 1.26, '1/1/2001')
DECLARE
@sql NVARCHAR(max),
@dates NVARCHAR(max)
-- I separated this to make the code easier to read
SET @dates = STUFF(
(
SELECT N',[' + CONVERT(VARCHAR, DateColumn, 101) + ']' AS [text()]
FROM #TBL
GROUP BY DateColumn
ORDER BY DateColumn
FOR XML PATH('')
), 1, 1, N''
)
-- I will break this part of the code up below
SET @sql = N'SELECT
*
FROM (
SELECT
ColumnName,
ColumnValue,
CONVERT(VARCHAR, DateColumn, 101) AS DateString
FROM (
SELECT
CAST(NameColumn AS VARCHAR(100)) AS NameColumn,
CAST(PriorityColumn AS VARCHAR(100)) AS PriorityColumn,
CAST(AnotherColumn AS VARCHAR(100)) AS AnotherColumn,
DateColumn
FROM #TBL
) P
UNPIVOT (
ColumnValue
FOR ColumnName IN (NameColumn, PriorityColumn, AnotherColumn)
) UNPIV
) P2
PIVOT (
MAX(ColumnValue)
FOR DateString IN (' + @dates + N')
) PIV'
EXECUTE dbo.sp_ExecuteSQL @sql
DROP TABLE #TBL
permet d'exécuter à travers ce un peu
-- I first do an UNPIVOT on all of the columns I want to pivot on, at the same time, converting them to the same datatype
SELECT
ColumnName,
ColumnValue,
CONVERT(VARCHAR, DateColumn, 101) AS DateString
FROM (
SELECT
CAST(NameColumn AS VARCHAR(100)) AS NameColumn,
CAST(PriorityColumn AS VARCHAR(100)) AS PriorityColumn,
CAST(AnotherColumn AS VARCHAR(100)) AS AnotherColumn,
DateColumn
FROM #TBL
) P
UNPIVOT (
ColumnValue
FOR ColumnName IN (NameColumn, PriorityColumn, AnotherColumn)
) UNPIV
Une fois que je fais cela, les données ressemblera à quelque chose comme ceci:
ColumnName ColumnValue DateString
----------------------------------
NameColumn a 01/01/2000
PriorityColumn 1 01/01/2000
AnotherColumn 7.2 01/01/2000
NameColumn a 01/02/2000
PriorityColumn 2 01/02/2000
AnotherColumn 8.9 01/02/2000
NameColumn a 01/03/2000
PriorityColumn 2 01/03/2000
AnotherColumn 53.2 01/03/2000
NameColumn a 01/04/2000
PriorityColumn 3 01/04/2000
AnotherColumn 9.12 01/04/2000
NameColumn b 01/01/2001
PriorityColumn 2 01/01/2001
AnotherColumn 1.26 01/01/2001
Ensuite, nous pouvons utiliser PIVOT comme ceci pour obtenir toutes les colonnes dont nous avons besoin:
PIVOT (
MAX(ColumnValue)
FOR DateString IN (' + @dates + N')
) PIV
Cela semble familier ... est thi s des mêmes exigences que la question que vous avez posée l'autre jour? – Aaronaught