【问题标题】:What is the difference between group by, distinct, Union for selecting distinct values for multiple columns?group by、distinct、Union 为多列选择不同值有什么区别?
【发布时间】:2009-08-13 12:28:53
【问题描述】:

This question 解释了一种获得多列不同组合的方法。但是我想知道用于此目的的 DISTINCT、UNION、GROUP BY 关键字方法的方法之间的区别。使用它们时我得到不同的结果。 我的查询是这样的 查询 1。

select 
column1,
column2,
column3
from table
group by 1,2,3

查询 2。

select distinct 
column1,
column2,
column3
from table

查询 3。

SELECT DISTINCT(ans) FROM (
    SELECT column1 AS ans FROM sametable
    UNION
    SELECT column2 AS ans FROM sametable
    UNION
    SELECT column3 AS ans FROM sametable
) AS Temp

对于上述查询,我​​得到了不同的行数(编辑:前两个给出的行数相同,但最后一个给出的行数不同)。任何机构都可以解释上述查询在做什么吗?尤其是第三个?

编辑:请注意,我在同一张桌子上做 UNION。那样的话会发生什么?

【问题讨论】:

    标签: sql group-by union distinct


    【解决方案1】:

    从我认为最简单的 DISTINCT 开始,真的就是这样。它返回不同的行组合。想想这个数据集:

    COL1      COL2      COL3
    A         B         C
    D         E         F
    G         H         I
    A         B         C   <- duplicate of row 1
    

    这将返回 3 行,因为数据集中的第 4 行与第一行完全匹配。 结果:

    COL1      COL2      COL3
    A         B         C
    D         E         F
    G         H         I
    

    GROUP BY 经常用于汇总和其他计算 选择 COL1,总和(COL2) 从表 按 column1 分组;

    对于这个数据集:

    COL1      COL2
    A         5
    A         6
    B         2
    C         3
    C         4
    C         5
    

    会回来

    COL1     SUM(COL2)
    A        11
    B        2
    C        12
    

    一个 UNION 只是从不同的查询中获取结果并将它们呈现为 1 个结果集:

    Table1
    COL1
    A
    
    Table2
    COLX
    B
    
    Table3
    WHATEVER_COLUMN_NAME
    Giddyup
    
    select COL1 from Table1
    UNION
    select COLX from Table2
    UNION 
    select WHATEVER_COLUMN_NAME from Table3;
    

    结果集:

    A
    B
    Giddyup
    

    执行联合时,列数据类型必须匹配。您不能将数字列与 char 列联合(除非您明确执行数据转换)

    【讨论】:

    • 谢谢。实际上,我对同一张桌子上的 UNION 两次感到困惑。当我们在同一张表上做 UNION 时,结果集是怎么来的?
    • 在您的示例中,您正在合并不同的列。因此,您实际上是采用基于行的数据,并将其呈现为基于列的数据。如果您有一个包含 4 个文本列和 1 行数据的表,并且您使用联合选择了每一列,那么您的结果集将是 1 列包含 4 行数据。
    • 需要注意的重要一点是联合丢弃重复项,而 UNION ALL 保留重复项 - sqlfiddle.com/#!3/83d93/1
    【解决方案2】:

    假设这是您的数据库数据:

    column1 | column2 | column3
    1       | 2       | 1
    1       | 2       | 2
    1       | 2       | 1
    3       | 1       | 2
    1       | 2       | 2
    1       | 2       | 2
    1       | 2       | 2
    

    第一次查询

    在第一个示例中,您将从数据库中获取所有列组合(因为 GROUP BY 1,2,3 不执行任何操作),包括重复项,因此它将返回:

    1       | 2       | 1
    1       | 2       | 2
    1       | 2       | 1
    3       | 1       | 2
    1       | 2       | 2
    1       | 2       | 2
    1       | 2       | 2
    

    第二次查询

    第二个示例采用列元组的唯一值,因此您将以

    结尾
    1       | 2       | 1
    1       | 2       | 2
    3       | 1       | 2
    

    第三次查询

    最后一个查询从三列中获取所有值,然后从该集合中删除重复项。因此,您将从任何表中获取所有值。最后这将返回

    1
    2
    3
    

    这说明清楚了吗?

    【讨论】:

    • 在某些 SQL 方言中,GROUP BY 1、2、3 表示“按第一、二、三列分组”,因此相当于第二个查询
    • 谢谢。但是如果你在同一张桌子上做 UNION 会发生什么? Group by 1,2,3 表示在 teradata sql 中按 column1,column2,column3 分组。所以第一个和第二个查询返回相同。
    • Group by 1,2,3 特定于某些 SQL 方言。有些人可能按第一列、第二列和第三列分组,其他人可能会忽略它。同一张表上的联合会将三列中的值合并为一列,以后可以过滤。我认为这些字段可能必须是相同/相似的类型。我不确定您是否可以将 INT 和 TEXT 字段合并。
    【解决方案3】:

    让我们来看一组样本数据

    orderid    customer orderdate
    1          B        July 29
    2          A        Aug 1
    3          A        Aug 4
    4          C        Aug 5
    5          B        Aug 6
    6          A        Aug 11
    

    Distinct 基本上返回给定记录的单个实例,结果集中没有整个列集的重复。例如:“从订单中选择不同的客户”将返回“A”、“B”、“C”,默认为所选列的 alpha 顺序。

    Group by 是在查询的给定字段集内进行聚合。例如:

    select customer, count(*) as NumberOfOrders from Orders group by 1

    Would result with...
    A    3
    B    2
    C    1
    

    您还可以在查询中但在给定组内应用 distinct(仅一次)..

    按客户从订单组中选择客户,count(*) 作为 NumberOfOrders,count( distinct {month of orderdate} ) 作为 CustomerMonths

    Would result with
    A    3    1  (all orders were in August)
    B    2    2  (had orders in July and August)
    C    1    1  (only one order in August)
    

    联合是必须具有完全相同的结果格式、列名和字段序列的查询。假设您有一个与数据存档版本完全相同的结构的订单表。您只保留最近一年的当前数据,所有历史数据都被推送到存档。如果你想在一个查询中获取给定客户的所有订单活动,你会想要做一个联合

    从 CurrentOrders where customerid = ?? 中选择 customerid、orderdate、amount按 2 降序排列 联盟 从其中 customerid = ?? 的 ArchivedOrders 中选择 customerid、orderdate、amount

    第一个选择的 ORDER by 子句将驱动结果,所有后续记录都被拉入结果中。就像 SQL 说的去表一,得到所有合格的,然后排序。然后,转到表二,将所有符合条件的内容从表一中提取到现有的排序列表中。最终结果是所有记录。

    HTH

    【讨论】:

    • 非常感谢。你对 group by 的解释太棒了。您答案的最后 3 段非常有帮助。但是当你在同一张桌子上做 UNION 会发生什么? “按 1、2、3 分组”和“不同”也会给出相同的结果。谢谢
    • 不知道...从来没有实例需要那个...但是,您可以做的是根据第一次使用相同分组的结果进行第二次选择以“滚动-up”来自第二个实例表的公共元素。
    【解决方案4】:

    如果您包含“实际执行计划”(MS SQL Management Studio 中的 control + M),它将为您提供 SQL 引擎如何优化您的每个语句的图表。了解这一点将有助于您编写更好的查询。

    【讨论】:

    • 好吧..我问的是一般的sql。但我的问题出在 teradata sql 中。
    猜你喜欢
    • 2010-12-15
    • 2010-09-14
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 2015-05-23
    相关资源
    最近更新 更多