Tableau 'Exemple':
Considérez le tableau suivant nommé exemple
:
* -------------------- * | Id | UniqueColumnSet | | -------------------- | | 0 | foo,bar,qux | | 1 | foo,bar | | 2 | foo,qux | | 3 | foo | * -------------------- *
Tentative:
Je souhaite concaténer uniquement les valeurs de Col_A
, Col_B
et Col_C
qui sont uniques (uniquement l'ensemble unique). Voici ma tentative:
SELECT Id, CONCAT_WS(',', DISTINCT Col_A, Col_B, Col_C) UniqueColumnSet FROM Example
Résultat attendu:
* -------------------------- * | Id | Col_A | Col_B | Col_C | | -------------------------- | | 0 | foo | bar | qux | | 1 | foo | foo | bar | | 2 | foo | qux | qux | | 3 | foo | foo | foo | * -------------------------- *
Erreur reçue :
# 1064 - Vous avez une erreur dans votre syntaxe SQL; vérifiez le manuel qui correspond à votre version de serveur MariaDB pour la bonne syntaxe à utiliser près de 'DISTINCT Col_A, Col_B, Col_C) UniqueColumnSet FROM Exemple LIMIT 0, 25 'à la ligne 2
Je suis conscient que vous ne pouvez pas utiliser DISTINCT
comme celui-ci dans CONCAT_WS
. Quelle serait la méthode la plus efficace pour obtenir le résultat attendu?
3 Réponses :
Utilisez UNION
pour les faire pivoter dans la même colonne, puis utilisez GROUP_CONCAT ()
pour les concaténer. UNION
supprimera les doublons par défaut.
SELECT id, GROUP_CONCAT(col) AS UniqueColumnSet FROM ( SELECT id, col_a AS col FROM Example UNION SELECT id, col_b AS col FROM Example UNION SELECT id, col_c AS col FROM Example ) AS x GROUP BY id
Il y a deux approches auxquelles je peux penser.
La première consisterait à utiliser une expression à la place de Col_B qui vérifie si Col_B correspond à Col_A, et renvoie un NULL si c'est le cas. Même chose pour une expression pour vérifier Col_C pour voir si elle correspond à Col_A ou Col_B.
CONCAT_WS ignore les valeurs NULL, donc quelque chose comme ceci:
bar,foo
Les données d'exemple ne sont pas affichées dans un cas où les valeurs en double ne sont pas contiguës, par exemple
bar foo bar
la requête ci-dessus suppose que nous voulons retourner p >
SELECT t.id , CONCAT_WS(',' , t.Col_A , IF(t.Col_B IN (t.Col_A), NULL, t.Col_B) , IF(t.Col_C IN (t.Col_A,t.Col_B), NULL, t.Col_C) ) AS UniqueColumnSet FROM `example` t ORDER BY t.id
Je préfère la solution de Barmar, car c'est la plus lisible pour moi. Mais cela devrait aussi fonctionner:
| id | UniqueColumnSet | | --- | --------------------- | | 0 | ["bar", "foo", "qux"] | | 1 | ["bar", "foo"] | | 2 | ["foo", "qux"] | | 3 | ["foo"] |
Si vous êtes d'accord avec un tableau JSON, vous pouvez essayer ce "hack":
select id, json_keys(json_object(Col_A, '', Col_B, '', Col_C, '')) as UniqueColumnSet from Example;
Résultat: p >
select id, concat_ws(',', Col_A, NULLIF(Col_B, Col_A), -- NULL if Col_B = Col_A NULLIF(NULLIF(Col_C, Col_A), Col_B) -- NULL if Col_C = Col_A or Col_C = Col_B ) as UniqueColumnSet from Example
Ce type de problème est symptomatique d'une mauvaise conception de schéma