0

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

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 的值,因为当原始 case when 为真时,Else 子句不应执行。但是它抓住了它,然后在 else 子句中仍然执行该案例?

如何修复此代码以给我 fieldid = 2 或 fieldid = 35,但避免将它们都通配在一起导致名称重复?

编辑

这是表结构:

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

它使用 EAV 结构,因此示例记录可能是:

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

fieldid 2 和 35 是自定义字段“First Name”(在单独的表中定义),fieldid 3 和 36 是“Last Name”。

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

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”(我们在 Lists 表中使用一个数字 ID 命名字段 list.name当我们添加一个新用户时,我们的前端 Rails 应用程序会生成,所以我只提取这个数字以使视图看起来像一个 Rails 约定数据库表)

4

2 回答 2

3

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

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

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

于 2009-10-25T13:57:24.230 回答
1

里面的任何东西group_concat()都无法查看它运行的上下文。因此,您在一个组中有两行,一个带有fieldid=2,第二个带有fieldid=35,它将执行以下操作:

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

这解释了为什么“约翰”被多次返回。修复它的唯一方法是在group_concat().

编辑:

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

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

或者,group_concat(DISTINCT ...)如果两个值不能不同,您也可以这样做(否则您会得到例如“John,Johny”)。为什么你有两个 first_name/last_name 值呢?

于 2009-10-25T14:03:22.513 回答