MySQL CASE & # 8220; Else Case When & # 8221; se ejecuta cuando la condición previa es verdadera: ¿qué me estoy perdiendo?
Pregunta
Tengo una tabla que, debido al sistema de terceros que estamos usando, a veces tiene datos duplicados. Dado que el modelo utiliza un método EAV, no hay forma de filtrar esto con la " derecha " De esta manera, estoy agregando los datos a una vista. Sé que esto es un problema de recopilación de datos, pero es más fácil para mí corregirlos en el extremo de la pantalla que pasar por este sistema y potencialmente romper los datos y formularios existentes. Necesito marcar uno de los dos campos para ver si se ingresó uno o ambos, pero solo seleccione uno (de lo contrario, el nombre se muestra dos veces así: "John, John" en lugar de "John"). Aquí está mi código para la parte relevante:
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 se ingresan tanto fieldid 2 como fieldid 35, esperaría que esto solo devuelva el valor de fieldid = 2 y no el valor de fieldid = 35, ya que la cláusula Else no debería ejecutarse cuando el caso original es verdadero . Sin embargo, se está tomando eso y luego se sigue ejecutando el caso cuando está dentro de la cláusula else?
¿Cómo puedo corregir este código para que me proporcione fieldid = 2 O fieldid = 35, pero evito agruparlos juntos, lo que hace que el nombre se duplique?
EDIT
Aquí está la estructura de la tabla:
table: subscribers_data
subscriberid (int) fieldid (int) data (text)
Utiliza una estructura E-A-V por lo que un registro de muestra podría ser:
subscriberid fieldid data
1 2 John
1 3 Smith
1 35 John
1 36 Smith
siendo fieldid 2 y 35 el campo personalizado " Primer nombre " (definido en una tabla separada) y los ID de campo 3 y 36 son " Apellido " ;.
Aquí está la vista completa que estoy 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 se está utilizando como modelo para una aplicación de Ruby on Rails, por lo que estoy usando algo de pirateo creativo para falsificar un " user_id " que Rails espera (nombramos el campo lista.nombre en la tabla de Listas usando un ID numérico que nuestra aplicación Front-end de Rails genera cuando agregamos un nuevo usuario, así que estoy extrayendo solo este número para hacer que la vista se vea como un Rails -tabla de base de datos de convenciones)
Solución
Cualquier cosa dentro de group_concat ()
no tiene una manera de ver el contexto en el que se está ejecutando. Entonces, tiene dos filas en un solo grupo, una con fieldid = 2
y la segunda con fieldid = 35
, hará lo siguiente:
- fila de procesamiento con
fieldid = 2
...-
s.fieldid = 2
es verdadero, devuelves.data
-
- fila de procesamiento con
fieldid = 35
...-
s.fieldid = 2
es falso, intente con la parteelse
-
s.fieldid = 35
es verdadero, devuelves.data
-
Esto explica por qué es " John " devuelto varias veces. La única forma de solucionarlo es ejecutar una consulta diferente fuera de group_concat ()
.
EDIT:
Realmente tienes que hacerlo de esta manera, usa algo como esto en su lugar:
SELECT ...
min(CASE WHEN s.fieldid IN (2,35) THEN s.data ELSE NULL END) AS first_name
...
Alternativamente, puedes hacer group_concat (DISTINCT ...)
si los dos valores no pueden ser diferentes (de lo contrario obtendrías, por ejemplo, " John, Johny "). Sin embargo, ¿por qué tienes dos valores para first_name / last_name?
Otros consejos
No soy un tipo de mysql, pero en una declaración de caso de servidor SQL, podría hacerlo sin el primer 'else'
case
when fieldid = 2 then data
when fieldid = 35 then data
else null
end
Además, parece que estás devolviendo el mismo campo de 'datos' en ambos casos