【问题标题】:MySQL Case 函数行为奇怪且不一致
【发布时间】:2022-01-03 05:13:21
【问题描述】:

我们使用 MySQL 8 作为我们的 Java 应用程序数据库。

我们有一个格式如下的查询:

select 
id,
group_concat(NAME ORDER BY ID separator ',,') AS Code,
CASE
WHEN MAX(p.VARIABLEfactor) = 1 THEN MAX(i.factor) ELSE MAX(p.factor) END AS factor

from MA_TABLE
join TABLE_P p on (...)
join TABLE_I i on (...)

 group by id

查询在我们的开发环境中运行良好,直到与因子列变为空的客户端一起部署。

我们已经在 MySQL Workbench 的客户端环境中运行了相同的查询,我们可以看到因子列填充得很好。

经过一些调试,我们改变了:

CASE
WHEN MAX(p.VARIABLEfactor) = 1 THEN MAX(i.factor) ELSE MAX(p.factor) END AS factor

MAX(
WHEN p.VARIABLEfactor = 1 THEN i.factor ELSE p.factor END ) AS factor,

并且查询正常工作。

这里有什么帮助吗?

【问题讨论】:

  • 他们做不同的事情,结果应该不同,他们没有任何可比性。请描述您正在尝试做什么,我们将帮助您确定哪个(如果有的话)是正确的。
  • 帮助什么?这里的目标是什么?
  • My first question is what make the same query to return expected data when run in workbench but return records with empty factor column when run within my java application :这很简单。要么每个场景的数据不同,要么每个场景的代码不同。也许一个正在针对测试数据库或不同客户端的数据运行。也许 java 正在丢弃或以其他方式破坏返回的值。但以下情况仍然正确:SQL 不能为相同的数据返回不同的结果,您修改后的 CASE not 做同样的计算。
  • 请运行此程序并将结果添加到您的问题中(仅限于您知道有问题的单个 id SELECT MA_TABLE.id, MA_TABLE.VARIABLEfactor, CASE WHEN i.factor IS NULL THEN 1 ELSE 0 END AS i_factor_null, CASE WHEN p.factor IS NULL THEN 1 ELSE 0 END AS p_factor_null, COUNT(*) AS row_count FROM MA_TABLE join TABLE_P p on (...) join TABLE_I i on (...) WHERE MA_TABLE.id = ????? GROUP BY 1, 2, 3, 4 ORDER BY 1, 2, 3, 4 最好来自 java 应用程序和 MySQL工作台。
  • 猜测你的意思是调试查询给出了太多行?这可能会提供更少的行(您仍然需要为一个问题 id 运行它)SELECT MA_TABLE.id, CASE WHEN MA_TABLE.VARIABLEfactor < 1 THEN '<1' WHEN MA_TABLE.VARIABLEfactor = 1 THEN '=1' WHEN MA_TABLE.VARIABLEfactor > 1 THEN '>1' END AS VARIABLE, CASE WHEN i.factor IS NULL THEN 1 ELSE 0 END AS i_factor_null, CASE WHEN p.factor IS NULL THEN 1 ELSE 0 END AS p_factor_null, COUNT(*) AS row_count FROM MA_TABLE join TABLE_P p on (...) join TABLE_I i on (...) WHERE MA_TABLE.id = ??? GROUP BY 1, 2, 3, 4 ORDER BY 1, 2, 3, 4

标签: mysql sql group-by aggregate-functions


【解决方案1】:

从您的解释中,我了解到您不理解两种 case 表达式的区别。但它们非常不同。让我们看一个 ID 的示例:

ID VARIABLEfactor i.factor p.factor
100 0 null 10
100 1 null 20

你的表情

CASE WHEN MAX(p.VARIABLEfactor) = 1 THEN MAX(i.factor) ELSE MAX(p.factor) END

查看最大值 VARIABLEfactor,即 1,因此适用 THEN 情况并返回最大值 i.factor。这是 null,因为所有 i.factor 都是 null。

你的表情

MAX(WHEN p.VARIABLEfactor = 1 THEN i.factor ELSE p.factor END)

查看每一行的VARIABLEfactor。对于第一行,这是 0,因此适用 ELSE 情况并使用 p.factor 10。对于第二行,VARIABLEfactor 为 1,因此使用其 i.factor null。其中你取最大值,即 10。

回顾一下:第一个表达式只是聚合结果上的CASE 表达式。它在这里返回 null。第二个表达式是条件聚合。它为样本数据返回 10。

【讨论】:

  • MAX(VARIALBEfactor) 也有可能大于 1。但是,是的,主要问题是 OP 不理解代码在做什么...dbfiddle.uk/…
  • 对于相同的 id,我将始终拥有来自 TABLE_P 和 TABLE_I 的相同记录(而不是相同的因子和变量因子)
  • 在工作台中正确执行了相同的查询,但在我的应用程序中为因子列返回空值
  • 解释我得到的结果的唯一逻辑解释是我的:CASE WHEN MAX(p.VARIABLEfactor) = 1 THEN MAX(i.factor) ELSE MAX(p.factor) END Is不考虑 group by 子句
  • @zizou 不,不,不。停止使用魔法思维。如果该表达式给出 NULL,那么(该组中的)列之一充满了 NULL。转到此答案的第一条评论中的链接,使用它并尝试复制您的断言。如果你不能复制它,你就不能做出断言。然后运行我在 cmets 中询问的代码。这将诊断您何时何地拥有 NULL。开始倾听在 SQL、调试和诊断方面拥有数十年经验的人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-15
  • 2016-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多