CASO MySQL "Else Case When" viene eseguito quando il presupposto è vero: cosa mi sto perdendo?

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

  •  06-07-2019
  •  | 
  •  

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)

È stato utile?

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, restituisce s.data
  • elaborazione riga con fieldid = 35 ...
    • s.fieldid = 2 è falso, prova la parte else
    • s.fieldid = 35 è vero, restituisce s.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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top