繁体   English   中英

分组时打印哪一列找到具有相同值的多行?

[英]Which column is printed when grouping by finds multiple rows with same value?

在此处输入图片说明

所以我的问题是,如果我在这个结果集上按 ContacType 分组,我将得到 3 行,一个用于 TMV,一个用于 TEL,另一个用于 EML,但是如果我打印 ContactValue 列,哪一个将打印用于 TMV 和 TEL? 是每个人第一次出现吗?342222 和 33333?还是分组时有特定的顺序?

为了使您所描述的查询成为有效的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM