2009-10-25 9 views
0

J'ai une table qui, en raison du système tiers que nous utilisons, a parfois des données en double. Comme le modèle utilise une méthode EAV, il n'y a aucun moyen de filtrer la "bonne" manière, donc j'agrège les données dans une vue - Je sais que c'est un problème de collecte de données mais il est plus facile pour moi de le réparer. passer par ce système et potentiellement casser les données et les formulaires existants. J'ai besoin de cocher 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 comme ceci: "John, John" au lieu de simplement "John"). Voici mon code pour la partie pertinente:MySQL CASE "Else Case When" est en cours d'exécution lorsque la condition est vraie - qu'est-ce qui me manque?

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 les deux fieldid 2 et FieldID 35 sont entrés, j'attendre à ce que pour revenir seulement la valeur de fieldid = 2 et non la valeur de fieldid = 35, puisque Else La clause ne doit pas s'exécuter lorsque le cas d'origine est vrai. Cependant, il saisit cela, et puis encore en cours d'exécution à l'intérieur de la clause else?

Comment puis-je corriger ce code pour me donner fieldid = 2 OU fieldid = 35, mais éviter de les regrouper ensemble ce qui entraîne la duplication du nom?

EDIT

Voici la structure de la table:

table: subscribers_data 
subscriberid (int) fieldid (int) data (text)  

Il utilise une structure EAV donc un enregistrement de l'échantillon pourrait être:

subscriberid   fieldid   data 
1      2    John 
1      3    Smith 
1      35    John 
1      36    Smith 

avec fieldid 2 et 35 étant champ personnalisé "Prénom" (défini dans une table distincte) et fieldid 3 et 36 étant "Nom".

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, alors j'utilise quelques bidouillages créatif pour un faux " user_id "que Rails attend (nous nommons le champ list.name dans la table Lists en utilisant un identifiant numérique que notre application Rails frontaux génère lorsque nous ajoutons un nouvel utilisateur, donc j'extrais juste ce nombre pour que la vue ressemble à une table de base de données Rails-convention)

Répondre

1

Tout l'intérieur group_concat() n'a pas une façon de voir le contexte dans lequel il est en cours d'exécution. Donc, vous avez avoir deux lignes dans un seul groupe, l'un avec fieldid=2 et deuxième avec fieldid=35, il fera comme suit:

    ligne de traitement
  • avec fieldid=2 ...
    • s.fieldid = 2 est vrai, le retour s.data
  • ligne de traitement avec fieldid=35 ...
    • s.fieldid = 2 est faux, essayez la partie else
    • s.fieldid = 35 est vrai, le retour s.data

Ce qui explique pourquoi "John" est revenu à plusieurs reprises. La seule façon de résoudre le problème consiste à exécuter une requête différente en dehors de group_concat().

EDIT:

Ih vous avez vraiment de le faire de cette façon, utiliser quelque chose comme ceci:

SELECT ... 
    min(CASE WHEN s.fieldid IN (2,35) THEN s.data ELSE NULL END) AS first_name 
... 

Sinon, vous pouvez le faire group_concat(DISTINCT ...) si les deux valeurs ne peuvent pas être différents (sinon vous obtiendriez par exemple "John, Johny"). Pourquoi avez-vous deux valeurs pour first_name/last_name?

+0

Une idée de comment le gérer? Je peux enlever group_concat de l'échantillon que j'ai montré ci-dessus et cela semble fonctionner, mais le faire à un autre (avec des ID différents) ne me donne aucun résultat même quand ils sont tous les deux là, mais en gardant group_concat me le donne deux fois. –

+0

Publiez la requête actuelle que vous exécutez et la structure de la table. –

+0

L'utiliser sans group_concat ne semble pas non plus me donner de données pour certains enregistrements où les données existent. C'est très bizarre et déroutant. –

2

Je ne suis pas un mec mysql, mais dans une déclaration de cas de 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 retourner le même champ « données » dans les deux cas

+0

Le champ "data" est la chose EAV dont je parlais. Fieldid lie à une liste de champs personnalisés (prénom, etc mais il peut être et est défini plus d'une fois - les 2 et 35 sont "prénom") et les données sont les valeurs réelles (dans ce cas, les deux contiennent "John"). La chose est, cela me donne toujours les deux champs - je veux seulement l'un ou l'autre. –

+0

Fondamentalement, j'ai eu le code ci-dessus au début: Il retourne "John, John" mais je veux juste être "John" –

+0

Vous allez devoir montrer plus de code, alors, WayneM. Que se passe-t-il autour de ce 'group_concat()'? –