À moins qu'une autre colonne ne dicte l'ordre des lignes d'entrée, il ne sera pas possible de garantir que les lignes de sortie sont retournées dans le même ordre. J'ai fait une hypothèse ici pour les ordonner par les valeurs des trois colonnes afin que le résultat soit déterministe.
Il est probablement possible de compacter ce code en moins d'étapes, mais montre les étapes raisonnablement clairement.
Notez que pour un grand ensemble de données, il peut être plus efficace de partitionner certaines de ces étapes en opérations SELECT INTO
créant des tables temporaires ou des tables de travail.
DECLARE @t TABLE
(col1 CHAR(1)
,col2 CHAR(1)
,col3 CHAR(1)
)
INSERT @t
SELECT 'd','b','c'
UNION SELECT 'a','d',NULL
UNION SELECT 'c','b',NULL
UNION SELECT 'a','b',NULL
UNION SELECT 'c','a',NULL
UNION SELECT 'c','a','d'
UNION SELECT 'c',NULL,NULL
;WITH freqCTE
AS
(
SELECT col1 FROM @t WHERE col1 IS NOT NULL
UNION ALL
SELECT col2 FROM @t WHERE col2 IS NOT NULL
UNION ALL
SELECT col3 FROM @t WHERE col3 IS NOT NULL
)
,grpCTE
AS
(
SELECT col1 AS val
,COUNT(1) AS cnt
FROM freqCTE
GROUP BY col1
)
,rowNCTE
AS
(
SELECT *
,ROW_NUMBER() OVER (ORDER BY col1
,col2
,col3
) AS rowN
FROM @t
)
,buildCTE
AS
(
SELECT rowN
,val
,cnt
,ROW_NUMBER() OVER (PARTITION BY rowN
ORDER BY ISNULL(cnt,-1) DESC
,ISNULL(val,'z')
) AS colOrd
FROM (
SELECT *
FROM rowNCTE AS t
JOIN grpCTE AS g1
ON g1.val = t.col1
UNION ALL
SELECT *
FROM rowNCTE AS t
LEFT JOIN grpCTE AS g2
ON g2.val = t.col2
UNION ALL
SELECT *
FROM rowNCTE AS t
LEFT JOIN grpCTE AS g3
ON g3.val = t.col3
) AS x
)
SELECT b1.val AS col1
,b2.val AS col2
,b3.val AS col3
FROM buildCTE AS b1
JOIN buildCTE AS b2
ON b2.rowN = b1.rowN
AND b2.colOrd = 2
JOIN buildCTE AS b3
ON b3.rowN = b1.rowN
AND b3.colOrd = 3
WHERE b1.colOrd = 1
ORDER BY b1.rowN
Ce sont trois colonnes différentes ou une colonne? –
ce sont des colonnes différentes –
les colonnes de vos données affichées représentent-elles des colonnes? si oui, pourquoi sont-ils en train d'être réorganisés? – TerrorAustralis