MySQL CASE & # 8220; Else Case When & # 8221; s'exécute lorsque la condition préalable est vraie - que me manque-t-il?
Question
J'ai une table qui, en raison du système tiers utilisé, contient parfois des données en double. Étant donné que le modèle utilise une méthode EAV, il n’est pas possible de filtrer cette option "droit". Ainsi, je suis en train d'agréger les données dans une vue. Je sais qu'il s'agit d'un problème de collecte de données, mais il est plus facile pour moi de la corriger du point de vue de l'affichage que de passer par ce système et éventuellement de casser des données et des formulaires existants. Je dois vérifier l'un des deux champs pour voir si l'un ou les deux sont entrés, mais n'en choisir qu'un (sinon le nom s'affiche deux fois de cette façon: "John, John" au lieu de "John"). Voici mon code pour la partie pertinente:
group_concat(
(
case when (`s`.`fieldid` = 2) then `s`.`data`
else
case when (`s`.`fieldid` = 35) then `s`.`data`
else NULL end
end
) separator ','),_utf8'') as first_name
Si fieldid 2 et fieldid 35 sont entrés, je m'attendrais à ce que cela retourne simplement la valeur de fieldid = 2 et non la valeur de fieldid = 35, car la clause Else ne devrait pas être exécutée lorsque le cas d'origine est true . Cependant, il s’agit de saisir cela, puis d’exécuter le cas quand on se trouve dans la clause else?
Comment puis-je corriger ce code pour me donner soit fieldid = 2 OU fieldid = 35, mais en évitant de les regrouper tous les deux, ce qui entraînerait la duplication du nom?
MODIFIER
Voici la structure de la table:
table: subscribers_data
subscriberid (int) fieldid (int) data (text)
Il utilise une structure E-A-V afin qu'un exemple d'enregistrement puisse être:
subscriberid fieldid data
1 2 John
1 3 Smith
1 35 John
1 36 Smith
avec les identifiants de champ 2 et 35 étant le champ personnalisé "Prénom" (défini dans une table séparée) et les identificateurs de champs 3 et 36 étant "Nom de famille".
Voici la vue complète que j'utilise:
select `ls`.`subscriberid` AS `id`,
left(`l`.`name`,(locate(_utf8'_',`l`.`name`) - 1)) AS `user_id`,
ifnull(group_concat((
case when (`s`.`fieldid` = 2) then `s`.`data`
when (`s`.`fieldid` = 35) then `s`.`data`
else NULL end) separator ','),_utf8'') AS `first_name`,
ifnull(group_concat((
case when (`s`.`fieldid` = 3) then `s`.`data`
when (`s`.`fieldid` = 36) then `s`.`data`
else NULL end) separator ','),_utf8'') AS `last_name`,
ifnull(`ls`.`emailaddress`,_utf8'') AS `email_address`,
ifnull(group_concat((
case when (`s`.`fieldid` = 81) then `s`.`data`
else NULL end) separator ','),_utf8'') AS `mobile_phone`,
ifnull(group_concat((
case when (`s`.`fieldid` = 100) then `s`.`data`
else NULL end) separator ','),_utf8'') AS `sms_only`
from ((`list_subscribers` `ls`
join `lists` `l` on((`ls`.`listid` = `l`.`listid`)))
left join `subscribers_data` `s` on((`ls`.`subscriberid` = `s`.`subscriberid`)))
where (left(`l`.`name`,(locate(_utf8'_',`l`.`name`) - 1)) regexp _utf8'[[:digit:]]+')
group by `ls`.`subscriberid`,`l`.`name`,`ls`.`emailaddress`
La vue est utilisée comme modèle pour une application Ruby on Rails. J'utilise donc un piratage créatif pour simuler un "utilisateur_id". que Rails attend (nous nommons le champ list.name dans le tableau Lists à l'aide d'un ID numérique généré par notre application Rails front-end lorsque nous ajoutons un nouvel utilisateur. J'extrais simplement ce nombre pour que la vue ressemble à un Rails. -convention base de données)
La solution
Tout élément contenu dans group_concat ()
ne permet pas de voir le contexte dans lequel il s'exécute. Donc, vous avez deux lignes dans un seul groupe, l’une avec fieldid = 2
et la seconde avec fieldid = 35
, il procédera comme suit:
- ligne de traitement avec
fieldid = 2
...-
s.fieldid = 2
est vrai, retournezs.data ??code>
-
- ligne de traitement avec
fieldid = 35
...-
s.fieldid = 2
est faux, essayez la partieelse
-
s.fieldid = 35
est vrai, retournezs.data ??code>
-
Ceci explique pourquoi "John" retourné plusieurs fois. Le seul moyen de résoudre ce problème consiste à exécuter une requête différente en dehors de group_concat ()
.
EDIT:
Si vous devez vraiment le faire de cette façon, utilisez quelque chose comme ceci à la place:
SELECT ...
min(CASE WHEN s.fieldid IN (2,35) THEN s.data ELSE NULL END) AS first_name
...
Vous pouvez également utiliser group_concat (DISTINCT ...)
si les deux valeurs ne peuvent pas être différentes (sinon, vous obtiendrez, par exemple, "John, Johny"). Pourquoi avez-vous deux valeurs pour prenom_nom / nom_dernier?
Autres conseils
Je ne suis pas un gars mysql, mais dans une déclaration de cas d'un serveur SQL, vous pouvez le faire sans le premier 'else'
case
when fieldid = 2 then data
when fieldid = 35 then data
else null
end
De plus, vous semblez renvoyer le même champ "données" dans les deux cas