CASO MySQL "Else Case When" viene eseguito quando il presupposto è vero: cosa mi sto perdendo?
Domanda
Ho una tabella che, a causa del sistema di terze parti che stiamo utilizzando, a volte ha dati duplicati. Poiché il modello utilizza un metodo EAV, non è possibile filtrare questo "diritto" in questo modo, quindi sto aggregando i dati in una vista: so che si tratta di un problema di raccolta dati, ma è più facile per me risolverlo sul display piuttosto che passare attraverso questo sistema e potenzialmente rompere i dati e i moduli esistenti. Devo controllare uno dei due campi per vedere se uno o entrambi sono stati inseriti, ma selezionarne solo uno (altrimenti il ??nome viene visualizzato due volte in questo modo: "John, John" anziché solo "John"). Ecco il mio codice per la parte 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
Se vengono immessi sia fieldid 2 che fieldid 35, mi aspetterei che questo restituisca solo il valore da fieldid = 2 e non il valore da fieldid = 35, poiché la clausola Else non dovrebbe essere eseguita quando il caso originale è vero . Tuttavia lo sta afferrando, e poi sta ancora eseguendo il caso quando è dentro la clausola else?
Come posso correggere questo codice per darmi fieldid = 2 OR fieldid = 35, ma evitare di metterli insieme entrambi, il che si traduce in una duplicazione del nome?
Modifica
Ecco la struttura della tabella:
table: subscribers_data
subscriberid (int) fieldid (int) data (text)
Utilizza una struttura E-A-V quindi un record di esempio potrebbe essere:
subscriberid fieldid data
1 2 John
1 3 Smith
1 35 John
1 36 Smith
con fieldid 2 e 35 come campo personalizzato "Nome" " (definito in una tabella separata) e fieldid 3 e 36 sono " Cognome " ;.
Ecco la vista completa che sto usando:
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 vista viene utilizzata come modello per un'applicazione Ruby on Rails, quindi sto usando un po 'di hacking creativo per falsificare un " user_id " che Rails si aspetta (chiamiamo il campo list.name nella tabella Lists usando un ID numerico che la nostra app Rails front-end genera quando aggiungiamo un nuovo utente, quindi sto estraendo solo questo numero per rendere la vista simile a Rails -convention database table)
Soluzione
Qualunque cosa all'interno di group_concat ()
non ha modo di vedere il contesto in cui è in esecuzione. Quindi, hai due righe in un singolo gruppo, una con fieldid = 2
e una seconda con fieldid = 35
, farà quanto segue:
- elaborazione riga con
fieldid = 2
...-
s.fieldid = 2
è vero, restituisces.data
-
- elaborazione riga con
fieldid = 35
...-
s.fieldid = 2
è falso, prova la parteelse
-
s.fieldid = 35
è vero, restituisces.data
-
Questo spiega perché è " John " restituito più volte. L'unico modo per risolverlo è eseguire una query diversa al di fuori di group_concat ()
.
Modifica
Ih devi davvero farlo in questo modo, usa invece qualcosa del genere:
SELECT ...
min(CASE WHEN s.fieldid IN (2,35) THEN s.data ELSE NULL END) AS first_name
...
In alternativa, puoi fare group_concat (DISTINCT ...)
se i due valori non possono essere diversi (altrimenti potresti ottenere ad es. " John, Johny "). Perché hai due valori per first_name / last_name?
Altri suggerimenti
Non sono un ragazzo mysql, ma in un'istruzione case del server sql, potresti farlo senza il primo "altro"
case
when fieldid = 2 then data
when fieldid = 35 then data
else null
end
Inoltre, sembra che tu stia restituendo lo stesso campo "dati" in entrambi i casi