0
votes

Comment puis-je concaténer uniquement des colonnes uniques dans MySQL pour chaque ligne?

Comment puis-je concaténer uniquement les colonnes uniques pour les colonnes spécifiées pour chaque ligne dans MySQL?

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?


1 commentaires

Ce type de problème est symptomatique d'une mauvaise conception de schéma


3 Réponses :


2
votes

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


0 commentaires

1
votes

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


0 commentaires

1
votes

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"]               |

db-fidle

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

db-fiddle


0 commentaires