[英]Which column is printed when grouping by finds multiple rows with same value?
为了使您所描述的查询成为有效的 ANSI SQL,您必须指定一个要用于ContactValue
列的聚合函数。 例如,如果您想要每种类型按字母顺序排列的最早联系人值,您可以编写:
SELECT
ContactType,
MIN(ContactValue) AS ContactValueFirst
FROM yourTable
GROUP BY
ContactType;
MySQL 的独特之处在于它有一个名为ONLY_FULL_GROUP_BY
的服务器模式,当禁用时,它实际上允许以下查询:
SELECT
ContactType,
ContactValue
FROM yourTable
GROUP BY
ContactType;
您的实际问题可能是在这种情况下会返回哪个联系人值。 最佳实践是甚至不要依赖这个服务器模式漏洞,而是始终按照我给出的第一个方法使用查询。 一个主要原因是,如果您编写代码时假设ONLY_FULL_GROUP_BY
模式被禁用,如果该模式被启用,您现有的代码可能会中断。
来自ONLY_FULL_GROUP_BY
模式的 文档:
如果 ONLY_FULL_GROUP_BY 被禁用……服务器可以自由地从每个组中选择任何值,所以除非它们相同,否则选择的值是不确定的,这可能不是你想要的。 此外,添加 ORDER BY 子句不会影响从每个组中选择值。
您不应运行产生不确定结果的查询。 如果这样做,您可能会在代码中产生错误。
实际上,当您执行像您显示的查询时,当前版本的 MySQL 会返回按索引顺序读取的第一个值。 返回的值取决于查询使用的索引。 这可能会发生变化,具体取决于您从表中添加或删除哪些索引,或者它可能会根据优化器选择读取哪个索引而发生变化。
MySQL 的未来版本可能会更改实现。 他们没有义务保留非标准行为。 所以如果你试图依赖这个“特性”,如果你升级了你的 MySQL 版本,你会得到一个惊喜。 它可能会导致您的应用程序中出现难以检测的错误。
此外,不同的 SQL 数据库实现可能会有不同的行为方式。 例如,SQLite 是我所知道的唯一允许此类模糊查询的其他数据库,但 SQLite 返回按索引顺序读取的最后一个值。 为什么? 只是因为他们实施它的方式。 无论如何,这是非标准和任意的行为,因此不能称为错误。
这就是为什么创建具有此类可变结果的查询是一个坏主意的原因。 它可能会导致令人困惑的应用程序行为。
在所有其他流行的 SQL 数据库(PostgreSQL、Oracle、Microsoft 等)中,运行此类查询只是一个错误。
这也是 ANSI SQL 规范中的一个错误。 当ONLY_FULL_GROUP_BY
被禁用时,MySQL 允许使用无效的 SQL。 你应该尽量避免它。
重新评论蒂姆的回答:
这里的想法是,实体 BBB 将具有优先权,所以按 ContactType 分组我首先想要 BBB 实体的所有联系人,现在在这种情况下只有 AAA 有电子邮件(EML),所以我知道它会正常返回。 问题是您在两个实体(BBB 和 AAA)中都有电话(TEL)和手机(TMV),但在这种情况下我需要 BBB。 那是我首先按 BBB 排序,然后按 AAA 排序,认为 Group By 将返回与 group by 列 (ContactType) 关联的 ContactValue 的第一次出现。
这听起来应该用窗口函数来解决,而不是 GROUP BY。 为此,您必须使用 MySQL 8.0 或更高版本。
WITH OrderedContacts AS (
SELECT Entity, ContactType, ContactValue,
ROW_NUMBER() OVER (PARTITION BY ContactType ORDER BY Entity DESC) AS rownum
FROM Contacts
)
SELECT * FROM OrderedContacts WHERE rownum = 1
ORDER BY Entity DESC
将 BBB 放在首位,如果给定联系人类型存在 BBB。 然后是AAA。 所以如果有 BBB,它得到第 1 行。如果没有 BBB,那么 AAA 得到第 1 行。这样每个联系人类型只返回一行,BBB 自然会获得“优先级”。
如果您使用 min 或 max 作为联系值,那么它将返回该联系类型的最小值或最大值。
示例:在此将按联系人类型升序排列
SELECT ContactType, MIN(ContactValue) AS ContactValueFirst FROM yourTable GROUP BY ContactType Order by 1
输出:
Contacttype Contactvalue EML China@port.com TEL 914444444 TMV。 312222
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.