Code前端首页关于Code前端联系我们

SQL 高级 - GROUP BY 和 PARTITION BY 的含义!

terry 2年前 (2023-09-26) 阅读数 66 #后端开发
SQL进阶——GROUP BY和PARTITION BY的意义!

本文将向您介绍GROUP BY和PARTITION BY的含义。

在 SQL 函数中,GROUP BY 和 PARTITION BY 非常相似 - 或者几乎相同。另外,两者都有数学理论基础。本文将围绕集合论群论中的重要概念“类”来阐明GROUP BY和PARTITION BY的含义。

使用SQL检索异构数据时,一个常见的操作是按照一定的标准组合数据。不仅是在使用SQL的时候,在我们日常生活中对数据进行排序或者分析的时候,我们也经常需要对数据进行组合。

具有分组功能的SQL语句有GROUP BY和PARTITION BY,它们都可以根据特定的列对表进行分组。唯一的区别是GROUP BY 在之后将每个组合并为一行数据。

例如,有一个像下面这样的表,存储了多个团队及其成员的信息。

团队SQL进阶——GROUP BY和PARTITION BY的意义!

在此表上使用 GROUP BY 或 PARTITION BY 来检索有关团队的信息。无论采用哪种方式,都可以将原始Teams表拆分为以下子集,然后使用SUM函数合并,或者使用RANK函数计算排名。

SELECT 
  member, 
  team, 
  age,
  RANK() OVER(PARTITION BY team ORDER BY age DESC) rn,
  DENSE_RANK() OVER(PARTITION BY team ORDER BY age DESC) dense_rn,
  ROW_NUMBER() OVER(PARTITION BY team ORDER BY age DESC) row_num
FROM Members
ORDER BY team, rn;

结果:SQL进阶——GROUP BY和PARTITION BY的意义!

分割后的子集如下图所示。 SQL进阶——GROUP BY和PARTITION BY的意义!

一般来说,集合用圆圈表示。不过,为了让“”(剪切)操作看起来更直观,特意用直线来划分子集。

接下来我们将重点关注分区子集,我们会发现它们具有以下三个属性。

1.全部都是空集合。

2。所有子集的并集等于除法之前的集合。

3.两个子集之间不存在交集。

由于这些子集是由表中存在的“team”列值分割的,因此它不能是空字符串。而且,当所有划分的子集加在一起时,很明显它们是原始集合。也就是说,分区后就没有非专有成员了。

也没有成员同时属于两个小组(=同时属于多个团队)。成员只需属于分区后的某个子集即可。所以我们也可以认为GROUP BY和PARTITION BY都是用来划分团队成员的函数。

在数学中,满足以上三个性质的任意子集称为“类”(划分),将原始集合划分为若干类的操作称为“排序”。这些是群论等领域的术语。划分的类与“分类”中的“类”含义相同,很容易理解。

SQL 中 PARTITION BY 子句的名称来自于类(即分区)的概念。尽管我们可以指定 GROUP BY 子句也使用此名称,因为它按分类执行分组操作,但使用不同的名称以避免歧义。一般来说,集合可以通过不同的方式进行分类。 SQL 也是如此。如果更改 GROUP BY 和 PARTITION BY 列,生成的分组也会相应更改。

在 SQL 中,GROUP BY 的使用非常频繁。由此我们可以知道,我们身边还有很多班级。例如学校的班级、学生的出生地等。没有学生的班级没有任何意义,出生地在两个省份的人不应该存在(可能有出生地不明的人,但这样的人应该属于列为NULL的类别)。

卡片也同样如此。 52张牌按图案可分为4类,按花色可分为红、黑两大类。同一类的元素满足与朋友相同的标准 - 至少与另一类的元素一样接近(从数学上讲,这种关系称为“对等关系”)。用一个不太恰当的词来说,就是“物以类聚,物以类聚”。

在群论中,划分类根据不同的分类方法有不同的名称。群论中有很多非常有趣的类,比如“留数类”。顾名思义,它指的是类除以整数的余数(一般情况下,类不一定是数字的集合,但现在我们只考虑数字的情况)。

例如,将自然数集合N对3进行余数排序后,我们将得到以下3类。

残留类别 0:M1 = {0, 3, 6, 9, …}

残留类别 1:M2 = {1, 4, 7, 10, …}

残留类别 2:M2 = { 2, 5, 8, 11, ...}

从第二类性质,我们知道这三类涵盖了所有自然数。这种情况可以用下面的公式来描述。

M1 + M2 + M3 = N

我们将这 3 个类别称为“ 模 3 剩余类别 ”。 Modul指除数,英文为Modulo。与类相比,模块的概念有些抽象且难以理解。

该模块也是用SQL实现的,是一个模MOD函数。尽管标准 SQL 中没有定义,但它在大多数数据库中实现(SQL Server 中使用 % 运算符)。在 SQL 中,它的常用用法如下。

--对从1到10的整数以3为模求剩余类
SELECT 
  MOD(num, 3) AS modulo,
  num
FROM Natural
ORDER BY modulo, num;

结果:SQL进阶——GROUP BY和PARTITION BY的意义!

残基类还具有许多有趣的特性,并且可以具有广泛的应用。例如,残差类搜索会将自然数集合划分为若干个大小相等的类,因此当需要从大量数据中采样一定比例时非常方便。例如,使用以下查询语句将数据随机收缩到原始大小的五分之一(如果表没有连续编号的列,只需使用 ROW_NUMBER 函数对其进行重新编号)。

--从原来的表中抽出(大约)五分之一行的数据
SELECT *
FROM SomeTbl
WHERE MOD(seq, 5) = 0;

--表中没有连续编号的列时,使用ROW_NUMBER函数就可以了
SELECT *
FROM (SELECT col,
             ROW_NUMBER() OVER(ORDER BY col) AS seq
     FROM SomeTbl)
WHERE MOD(seq, 5) = 0;

当然,在现实中,表中数据的行数可能不完全是5的倍数,因此其余类的大小也不一定相同。但是,上面的查询语句绝对满足“将数据随机等分”的随机采样要求。

这篇文章是不是让你对的实现过程GROUP BY和PARTITION BY以及它们的数学基础有了更深入的了解呢?总的来说,SQL和关系数据库引入了大量集合论和群论的结果。

你可能会觉得这些内容有点抽象。嗯,它们确实很抽象,但正是因为它们的抽象性,它们才被广泛使用。数学理论不是脱离现实的游戏。事实上,它隐藏了许多我们可以在日常工作中使用的技能。但如果你只是等待,就很难找到它们了。数据工程师只有通过自己的努力搭建起理论与实践之间的桥梁,才能提高数学应用能力。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门