当前提条件为真时,MySQL CASE“Else Case When”正在执行 - 我错过了什么?

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

  •  06-07-2019
  •  | 
  •  

我有一个表,由于我们使用的是第三方系统,有时会有重复的数据。由于模型使用 EAV 方法,因此无法以“正确”的方式对其进行过滤,因此我将数据聚合到视图中 - 我知道这是一个数据收集问题,但对我来说在显示端修复它比在显示端修复它更容易浏览这个系统并可能破坏现有的数据和表格。我需要检查两个字段之一,看看是否输入了一个或两个字段,但只选择一个(否则名称会显示两次,如下所示:“约翰,约翰”而不仅仅是“约翰”)。这是我相关部分的代码:

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

如果同时输入了 fieldid 2 和 fieldid 35,我希望它只返回 fieldid = 2 中的值,而不是 fieldid = 35 中的值,因为当原始情况为 true 时,Else 子句不应执行。然而,它抓住了这一点,然后仍然在 else 子句内执行该案例?

如何修复此代码以提供 fieldid = 2 或 fieldid = 35,但避免将它们组合在一起导致名称重复?

编辑

这是表结构:

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

它使用 E-A-V 结构,因此示例记录可能是:

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

其中 fieldid 2 和 35 是自定义字段“名字”(在单独的表中定义),fieldid 3 和 36 是“姓氏”。

这是我正在使用的完整视图:

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`

该视图被用作 Ruby on Rails 应用程序的模型,因此我使用一些创造性的黑客技术来伪造 Rails 期望的“user_id”(我们使用数字 ID 在 Lists 表中命名字段 list.name当我们添加新用户时,我们的前端 Rails 应用程序会生成,因此我只提取这个数字以使视图看起来像 Rails 约定数据库表)

有帮助吗?

解决方案

里面有什么东西 group_concat() 没有办法查看它运行的上下文。因此,一个组中有两行,其中一行包含 fieldid=2 第二个是 fieldid=35, ,它将执行以下操作:

  • 处理行与 fieldid=2...
    • s.fieldid = 2 为真,返回 s.data
  • 处理行与 fieldid=35...
    • s.fieldid = 2 是假的,试试 else 部分
    • s.fieldid = 35 为真,返回 s.data

这解释了为什么“John”被多次返回。解决这个问题的唯一方法是在外部运行不同的查询 group_concat().

编辑:

嗯,你真的必须这样做,请改用这样的东西:

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

或者你可以这样做 group_concat(DISTINCT ...) 如果两个值不能不同(否则你会得到例如“约翰,约翰尼”)。为什么名字/姓氏有两个值?

其他提示

我不是一个mysql人,但是在一个sql server case语句中,你可以在没有第一个'else'的情况下做到这一点

case
  when fieldid = 2 then data
  when fieldid = 35 then data
  else null
end

此外,您似乎在两种情况下都返回相同的“数据”字段

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top