MySQL CASE“否则情况”当前提条件为真时正在执行 - 我错过了什么?

发布于 2024-08-08 19:23:59 字数 2450 浏览 1 评论 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 中的值,因为 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 是自定义字段“名字”(在单独的表中定义),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”(我们将字段命名为列表)列表表中的 .name 使用我们的前端 Rails 应用程序在添加新用户时生成的数字 ID,因此我只提取这个数字以使视图看起来像 Rails 约定数据库表)

I have a table that, due to the third party system we are using, sometimes has duplicate data. Since the model uses an EAV method there's no way to filter this the "right" way, so I am aggregating the data into a View - I know this is a data collection problem but it's easier for me to fix it on the display end than go through this system and potentially break existing data and forms. I need to check one of two fields to see if one or both are entered, but only pick one (otherwise the name displays twice like this: "John,John" instead of just "John"). Here's my code for the relevant part:

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

If both fieldid 2 and fieldid 35 are entered, I would expect this to just return the value from fieldid = 2 and not the value from fieldid = 35, since the Else clause shouldn't execute when the original case when is true. However it's grabbing that, and then still executing the case when inside of the else clause?

How can I fix this code to give me either fieldid = 2 OR fieldid = 35, but avoid globbing them both together which results in the name being duplicated?

EDIT

Here is the table structure:

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

It uses an E-A-V structure so a sample record might be:

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

with fieldid 2 and 35 being the custom field "First Name" (defined in a separate table) and fieldid 3 and 36 being "Last Name".

Here is the full view that I'm using:

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`

The view is being used as the Model for a Ruby on Rails application, so I'm using some creative hacking to fake out a "user_id" that Rails expects (we name the field list.name in the Lists table using a numeric ID that our front-end Rails app generates when we add a new user, so I'm extracting just this number to make the view look like a Rails-convention database table)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天涯沦落人 2024-08-15 19:23:59

我不是 mysql 人员,但是在 sql server case 语句中,您可以在没有第一个“else”的情况下完成它

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

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

I am not a mysql guy, but in a sql server case statement, you could do it without the first 'else'

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

Also, you seem to be returning the same 'data' field in both cases

岛歌少女 2024-08-15 19:23:59

group_concat() 中的任何内容都无法查看其运行的上下文。因此,单个组中有两行,第一行包含 fieldid=2,第二行包含 fieldid=35,它将执行以下操作:

  • 使用 处理行字段id=2...
    • s.fieldid = 2为true,返回s.data
  • 处理带有 fieldid=35 的行...
    • s.fieldid = 2 为 false,请尝试 else 部分
    • s.fieldid = 35为true,返回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 ...)不同(否则你会得到例如“John,Johny”)。为什么名字/姓氏有两个值?

Anything inside group_concat() doesn't have a way to see the context in which it's running. So, you have have two rows in a single group, one with fieldid=2 and second with fieldid=35, it will do the following:

  • processing row with fieldid=2...
    • s.fieldid = 2 is true, return s.data
  • processing row with fieldid=35...
    • s.fieldid = 2 is false, try the else part
    • s.fieldid = 35 is true, return s.data

This explains why is "John" returned multiple times. The only way to fix it is to run a different query outside of group_concat().

EDIT:

Ih you really have to do it this way, use something like this instead:

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

Alternatively you can do group_concat(DISTINCT ...) if the two values can't be different (otherwise you would get e.g. "John,Johny"). Why do you have two values for first_name/last_name though?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文