我应该在查询中使用 distinct
Should I use distinct in my queries
我工作的地方最近有人告诉我,在查询中使用 distinct 是程序员的坏标志。所以我想知道我猜不使用此功能的唯一方法是使用 group by 。
据我了解,distinct 函数的工作方式与 group by 非常相似,只是读取方式不同。一个独特的功能检查每个单独的选择标准与一组做同样的事情只是作为一个整体完成。
请记住,我只做 报告。我没有create/alter这个数据。所以我的问题是我应该使用 distinct 还是 group by 的最佳实践。如果两者都没有,那么没有其他选择。也许 group by 应该用在比我这里的非真实示例更复杂的查询中,但你明白了。我找不到真正解释为什么或为什么不应该在查询中使用 distinct 的答案
select distinct
spriden_user_id as "ID",
spriden_last_name as "last",
spriden_first_name as "first",
spriden_mi_name as "MI",
spraddr_street_line1 as "Street",
spraddr_street_line2 as "Street2",
spraddr_city as "city",
spraddr_stat_code as "State",
spraddr_zip as "zip"
from spriden, spraddr
where spriden_user_id = spraddr_id
and spraddr_mail_type = 'MA'
VS
select
spriden_user_id as "ID",
spriden_last_name as "last",
spriden_first_name as "first",
spriden_mi_name as "MI",
spraddr_street_line1 as "Street",
spraddr_street_line2 as "Street2",
spraddr_city as "city",
spraddr_stat_code as "State",
spraddr_zip as "zip"
from spriden, spraddr
where spriden_user_id = spraddr_id
and spraddr_mail_type = 'MA'
group by "ID","last","first","MI","Street","Street2","city","State","zip"
数据库很聪明,可以识别你的意思。我希望您的两个查询都能同样出色地执行。维护您的查询的其他人了解您的意思很重要。如果您真的想要检索不同的记录,请使用 DISTINCT
。如果您打算进行聚合,请使用 GROUP BY
看看this question。有一些不错的答案可能会有所帮助。
在您的示例中,distinct
和 group by
执行相同的操作。我认为您的同事的意思是您的查询首先不应 return 重复,并且您应该能够在没有 distinct
或 group by
子句的情况下编写查询。您也许可以通过扩展 join
条件来减少重复项。
询问他们为什么这是一种不好的做法。许多人通过阅读本书的第一页或 google 搜索的第一个结果来制定规则或想出他们认为不好的做法。如果它完成了工作并且没有引起任何问题,那么就没有理由通过寻找替代方案来创造更多的工作。从您发布的两个选项中,我也会使用 distinct,因为它更短且更易于阅读和维护。
@zedfoxus 提供的答案有助于理解上下文。
但是,如果数据设计正确,我认为您的查询不需要不同的记录。
看来您正在选择 table spriden
的主键,因此所有数据 应该 是唯一的。您还加入了 spraddr
table; table 是否真的包含有效的重复数据?或者是否可能需要一个额外的连接条件来过滤掉那些重复项?
这就是为什么我对使用“distinct
”感到紧张 - spraddr
table 可能包含您应该用来过滤数据的其他列,以及“distinct
" 可能隐藏了这一点。
此外,您可能会生成大量结果集,需要使用 "distinct" 子句进行过滤,这可能会导致性能问题。例如,如果 spriden
中的每一行在 spraddr
中有 100 万行,您应该使用 "is_current" 标志来查找 2 或 3 个 "real"。
最后,当我看到 "group by" 被用作 distinct 的替代品时,我感到很紧张,不是因为它是 "wrong",而是因为在风格上,我认为 group by 应该用于聚合函数。这只是个人喜好。
如果您的查询是正确的,DISTINCT 和 GROUP BY 提供相同的结果集,但您的同事说 DISTINCT 隐藏问题是正确的。如果您缺少联接并使用 GROUP BY,您将获得比预期更多的信息。如果您缺少联接并使用 DISTINCT,SQL 引擎将执行无界(或部分有界)联接,缩小结果范围,然后得出预期的答案。
除了生成不必要的数据会导致明显的性能下降之外,您还 运行 填满您的 tempdb 的风险(即:运行您的 tempdb 所在的硬盘驱动器空间不足生命)。
在生产中使用 GROUP BY。
谁告诉你使用 DISTINCT
是一个不好的标志,这本身就是错误的。实际上,这完全取决于您首先尝试使用 DISTINCT
来解决什么问题。
如果您查询的 table 是 预计 具有某些字段或字段组合的重复值,并且您报告的列表值或值的组合(并且不对它们执行任何聚合),那么 DISTINCT
是最明智的使用方法。在我看来使用 GROUP BY
并没有什么意义,只是因为有人认为 DISTINCT
不应该被使用。事实上,我认为这就是 DISTINCT
设计的目的。
如果你发现你的查询有一个错误意味着返回重复的值,你不应该使用 DISTINCT
或 GROUP BY
来消除这个错误。相反,您应该找出错误的原因并修复它。
使用 DISTINCT
作为安全网也是一种糟糕的做法,因为它可能隐藏问题,而且计算量大(通常为 O(n log n) 或 O(n2))。在这种情况下,我看不出使用 GROUP BY
对您有帮助。
是的,当我在某人的查询中遇到它时,Distinct 往往会在我的脑海中引起一点警觉。它在某些情况下当然是必需的,但大多数数据模型不应该需要它。它往往是不得不使用它的最后手段或异常情况。它也可能是位于数据库之上的不良应用程序的系统性,允许插入重复条目或将其更新为重复条目(同样,没有相应的数据库级别约束来防止此类操作)。所以首先要检查的是数据。这可能是糟糕的数据模型设计的标志。但很可能查询不应该进入 select 中重复行挥之不去的那个阶段。
在构建大型查询时,通常我会从指定唯一字段的子查询的块开始,之后的任何子查询都必须内连接或左连接,但从不添加或减少行数已经由 nugget 查询定义.. 并记住处理左连接的可能 NULL。
因此,例如,nugget 查询还可以通过使用分区 select 正确的行,例如,select 连接 table 的最新行,或者在那个阶段做一些其他分组。
在您的示例中,我不希望出现重复。如果一个人可以有历史地址,那很好,但是你是否需要查看所有地址,或者只查看最近的地址,如果有重复地址,对于同一个人,这是否意味着不正确的重复数据,或者是否意味着人离开了那个地址,但后来又回到了那里……在这种情况下,分区 select 将通过比不同的更好的控制来解决这个问题。尤其是当字段后来被其他人添加到查询中并破坏了不同的时候-ness.
这意味着所有其他数据都挂在子查询的这个块上。您将其他可能的字段粘贴到核心字段集的右侧。
如果 Distinct 是最后的手段,那么它们通常保留用于已知数据在 table 中对于那组字段具有重复条目的情况,这是完全正常的。在我看来,虽然 distinct 是计划中的一个缓慢的 post-select 过程,尤其是当返回的结果集很大时。我应该在这些日子里验证这一点。
我工作的地方最近有人告诉我,在查询中使用 distinct 是程序员的坏标志。所以我想知道我猜不使用此功能的唯一方法是使用 group by 。
据我了解,distinct 函数的工作方式与 group by 非常相似,只是读取方式不同。一个独特的功能检查每个单独的选择标准与一组做同样的事情只是作为一个整体完成。
请记住,我只做 报告。我没有create/alter这个数据。所以我的问题是我应该使用 distinct 还是 group by 的最佳实践。如果两者都没有,那么没有其他选择。也许 group by 应该用在比我这里的非真实示例更复杂的查询中,但你明白了。我找不到真正解释为什么或为什么不应该在查询中使用 distinct 的答案
select distinct
spriden_user_id as "ID",
spriden_last_name as "last",
spriden_first_name as "first",
spriden_mi_name as "MI",
spraddr_street_line1 as "Street",
spraddr_street_line2 as "Street2",
spraddr_city as "city",
spraddr_stat_code as "State",
spraddr_zip as "zip"
from spriden, spraddr
where spriden_user_id = spraddr_id
and spraddr_mail_type = 'MA'
VS
select
spriden_user_id as "ID",
spriden_last_name as "last",
spriden_first_name as "first",
spriden_mi_name as "MI",
spraddr_street_line1 as "Street",
spraddr_street_line2 as "Street2",
spraddr_city as "city",
spraddr_stat_code as "State",
spraddr_zip as "zip"
from spriden, spraddr
where spriden_user_id = spraddr_id
and spraddr_mail_type = 'MA'
group by "ID","last","first","MI","Street","Street2","city","State","zip"
数据库很聪明,可以识别你的意思。我希望您的两个查询都能同样出色地执行。维护您的查询的其他人了解您的意思很重要。如果您真的想要检索不同的记录,请使用 DISTINCT
。如果您打算进行聚合,请使用 GROUP BY
看看this question。有一些不错的答案可能会有所帮助。
在您的示例中,distinct
和 group by
执行相同的操作。我认为您的同事的意思是您的查询首先不应 return 重复,并且您应该能够在没有 distinct
或 group by
子句的情况下编写查询。您也许可以通过扩展 join
条件来减少重复项。
询问他们为什么这是一种不好的做法。许多人通过阅读本书的第一页或 google 搜索的第一个结果来制定规则或想出他们认为不好的做法。如果它完成了工作并且没有引起任何问题,那么就没有理由通过寻找替代方案来创造更多的工作。从您发布的两个选项中,我也会使用 distinct,因为它更短且更易于阅读和维护。
@zedfoxus 提供的答案有助于理解上下文。
但是,如果数据设计正确,我认为您的查询不需要不同的记录。
看来您正在选择 table spriden
的主键,因此所有数据 应该 是唯一的。您还加入了 spraddr
table; table 是否真的包含有效的重复数据?或者是否可能需要一个额外的连接条件来过滤掉那些重复项?
这就是为什么我对使用“distinct
”感到紧张 - spraddr
table 可能包含您应该用来过滤数据的其他列,以及“distinct
" 可能隐藏了这一点。
此外,您可能会生成大量结果集,需要使用 "distinct" 子句进行过滤,这可能会导致性能问题。例如,如果 spriden
中的每一行在 spraddr
中有 100 万行,您应该使用 "is_current" 标志来查找 2 或 3 个 "real"。
最后,当我看到 "group by" 被用作 distinct 的替代品时,我感到很紧张,不是因为它是 "wrong",而是因为在风格上,我认为 group by 应该用于聚合函数。这只是个人喜好。
如果您的查询是正确的,DISTINCT 和 GROUP BY 提供相同的结果集,但您的同事说 DISTINCT 隐藏问题是正确的。如果您缺少联接并使用 GROUP BY,您将获得比预期更多的信息。如果您缺少联接并使用 DISTINCT,SQL 引擎将执行无界(或部分有界)联接,缩小结果范围,然后得出预期的答案。
除了生成不必要的数据会导致明显的性能下降之外,您还 运行 填满您的 tempdb 的风险(即:运行您的 tempdb 所在的硬盘驱动器空间不足生命)。
在生产中使用 GROUP BY。
谁告诉你使用 DISTINCT
是一个不好的标志,这本身就是错误的。实际上,这完全取决于您首先尝试使用 DISTINCT
来解决什么问题。
如果您查询的 table 是 预计 具有某些字段或字段组合的重复值,并且您报告的列表值或值的组合(并且不对它们执行任何聚合),那么 DISTINCT
是最明智的使用方法。在我看来使用 GROUP BY
并没有什么意义,只是因为有人认为 DISTINCT
不应该被使用。事实上,我认为这就是 DISTINCT
设计的目的。
如果你发现你的查询有一个错误意味着返回重复的值,你不应该使用 DISTINCT
或 GROUP BY
来消除这个错误。相反,您应该找出错误的原因并修复它。
使用 DISTINCT
作为安全网也是一种糟糕的做法,因为它可能隐藏问题,而且计算量大(通常为 O(n log n) 或 O(n2))。在这种情况下,我看不出使用 GROUP BY
对您有帮助。
是的,当我在某人的查询中遇到它时,Distinct 往往会在我的脑海中引起一点警觉。它在某些情况下当然是必需的,但大多数数据模型不应该需要它。它往往是不得不使用它的最后手段或异常情况。它也可能是位于数据库之上的不良应用程序的系统性,允许插入重复条目或将其更新为重复条目(同样,没有相应的数据库级别约束来防止此类操作)。所以首先要检查的是数据。这可能是糟糕的数据模型设计的标志。但很可能查询不应该进入 select 中重复行挥之不去的那个阶段。
在构建大型查询时,通常我会从指定唯一字段的子查询的块开始,之后的任何子查询都必须内连接或左连接,但从不添加或减少行数已经由 nugget 查询定义.. 并记住处理左连接的可能 NULL。
因此,例如,nugget 查询还可以通过使用分区 select 正确的行,例如,select 连接 table 的最新行,或者在那个阶段做一些其他分组。
在您的示例中,我不希望出现重复。如果一个人可以有历史地址,那很好,但是你是否需要查看所有地址,或者只查看最近的地址,如果有重复地址,对于同一个人,这是否意味着不正确的重复数据,或者是否意味着人离开了那个地址,但后来又回到了那里……在这种情况下,分区 select 将通过比不同的更好的控制来解决这个问题。尤其是当字段后来被其他人添加到查询中并破坏了不同的时候-ness.
这意味着所有其他数据都挂在子查询的这个块上。您将其他可能的字段粘贴到核心字段集的右侧。
如果 Distinct 是最后的手段,那么它们通常保留用于已知数据在 table 中对于那组字段具有重复条目的情况,这是完全正常的。在我看来,虽然 distinct 是计划中的一个缓慢的 post-select 过程,尤其是当返回的结果集很大时。我应该在这些日子里验证这一点。