MySQL CASE & # 8220; Else Case When & # 8221; s'exécute lorsque la condition préalable est vraie - que me manque-t-il?

StackOverflow https://stackoverflow.com/questions/1620973

  •  06-07-2019
  •  | 
  •  

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)

Était-ce utile?

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, retournez s.data
  • ligne de traitement avec fieldid = 35 ...
    • s.fieldid = 2 est faux, essayez la partie else
    • s.fieldid = 35 est vrai, retournez s.data

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top