八个不可不知的SQL高级方法

news2024/12/22 22:11:35

结构化查询语言(SQL)是一种广泛使用的工具,用于管理和操作数据库。基本的SQL查询简单易学,但掌握高级SQL技术可以将您的数据分析和管理能力提升到新的高度。

高级SQL技术是指一系列功能和函数,使您能够对数据执行复杂操作,例如聚合、连接、子查询、窗口函数和递归查询。

通过深入了解SQL的高级特性和技巧,您可以更有效地进行数据分析和管理,为您的工作带来更大的价值。

本文将详细介绍以下技术,并使用具体且易于理解的示例。

1. 窗口函数

窗口函数支持在与当前行相关的一组行上执行计算,可以根据指定的窗口定义进行聚合、排序和分析操作。这种计算方式可以提供更灵活和精确的数据分析能力。

例如;有一个名为orders的表,其中包含以下列:order_id、customer_id、order_date和order_amount。您想要计算每个客户的销售总额,按其订单日期排序。您可以使用SUM窗口函数来实现这一点:

SELECT order_id, customer_id, order_date, order_amount,
  SUM(order_amount) OVER (
    PARTITION BY customer_id
    ORDER BY order_date
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS running_total
FROM orders;

在此示例中,SUM函数应用于order_amount列,并按customer_id列进行分区。这意味着每个客户的累计销售额将分别计算。

ORDER BY子句指定应使用订单日期来确定每个分区内行的顺序。这意味着将按客户订单的顺序计算累计销售额。

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW子句指定计算的窗口框架应包括从分区开始到当前行为止的所有行。这意味着将从每个客户的第一笔订单开始计算累计销售额,直到包括当前订单。

查询的结果将是一个包含与orders表相同列的表,以及一个名为running_total的附加列,其中包含每个客户的累计销售额,按其订单日期排序。

通过在SQL中使用窗口函数,您可以对数据执行复杂计算,并深入了解业务。此示例演示了如何为每个客户计算累计销售额,但是您可以使用窗口函数执行许多其他类型的计算,例如计算移动平均值、排名数据等。

2. 公共表达式(CTEs)

公共表达式(CTEs)支持您在SQL查询中定义一个临时结果集,并将其命名为一个表,以便在后续的SQL语句中引用和使用该临时结果集。这种方式可以提高查询的可读性和可维护性,并使查询逻辑更加模块化和灵活。

假设有一个名为employees的表,其中包含以下列:employee_id、employee_name、department_id和salary。您想要计算每个部门的平均工资,然后找到其工资高于部门平均工资的员工。为此,您可以使用CTE首先计算每个部门的平均工资,然后在第二个查询中使用该CTE查找其工资高于部门平均工资的员工。

WITH department_avg_salary AS (
  SELECT department_id, AVG(salary) AS avg_salary
  FROM employees
  GROUP BY department_id
)

SELECT employee_id, employee_name, salary, department_avg_salary.avg_salary
FROM employees
INNER JOIN department_avg_salary ON employees.department_id = department_avg_salary.department_id
WHERE salary > department_avg_salary.avg_salary;

在此示例中,第一个查询定义了一个名为department_avg_salary的CTE。该CTE使用AVG函数和GROUP BY子句计算每个部门的平均工资,将员工按其部门分组。

然后,第二个查询将department_avg_salary CTE视为表格,并将其与employees表格在department_id列上连接。结果由WHERE子句过滤,仅包括其工资高于其部门平均工资的员工。在这种情况下使用CTE的优点在于它允许您将问题分解为两个步骤:首先计算每个部门的平均工资,然后选择其工资高于其部门平均工资的员工。通过将计算分成两个步骤,查询更易于阅读和维护。

CTEs也可以用于许多其他情况,例如递归查询、复杂连接等。通过使用CTE,您可以使SQL查询更易于阅读和理解。

3. 聚合函数

聚合函数是用于对一组值进行计算并返回单个结果值的函数。它们可以在表的多行或多列之间执行计算,并且能够以有意义的方式对数据进行汇总。在SQL中,最常见的聚合函数包括SUM(求和)、AVG(平均值)、MIN(最小值)、MAX(最大值)和COUNT(计数)。这些函数在数据分析和报告中非常实用,可以帮助我们快速获得对数据集的总结统计信息。

例如,有一个名为sales的表,其中包含以下列:sale_id、product_id、sale_date、sale_amount和region。您想要计算每个产品的总销售额和平均销售额,以及每个地区的畅销产品。为此,您可以使用聚合函数按产品和地区分组销售,并计算总销售额和平均销售额,以及找到每个地区的畅销产品。

SELECT 
  product_id, 
  AVG(sale_amount) AS avg_sale_amount, 
  SUM(sale_amount) AS total_sale_amount, 
  region, 
  RANK() OVER (PARTITION BY region ORDER BY SUM(sale_amount) DESC) AS rank
FROM sales
GROUP BY product_id, region;

在此示例中,查询有三个聚合函数:AVG、SUM和RANK。

AVG函数计算每个产品和地区的平均销售额,而SUM函数计算每个产品和地区的总销售额。GROUP BY子句按产品和地区分组销售。

RANK函数用于查找每个地区的畅销产品。OVER子句指定应单独对每个地区进行排名,而PARTITION BY子句指定要对数据进行分区的列(在本例中为region)。ORDER BY子句指定排名应基于每个地区中每种产品的销售金额总和,并按降序排列。

查询结果包括product_id、region、total_sale_amount、avg_sale_amount和rank列。rank列指示每个地区中每种产品基于总销售额的排名,排名第一的畅销产品在每个地区都是1。

使用聚合函数,在这种情况下,优点在于它们允许您对数据进行分组和汇总,并计算有用的指标,例如总销售额和平均销售额。RANK函数还允许您查找每个地区的畅销产品,这对于识别趋势和改进机会非常有用。

聚合函数也可以用于许多其他情况,例如计算最小值和最大值、计数记录等。通过使用聚合函数,您可以使SQL查询更加强大和灵活。

4. 透视表

透视表是一种用于从较大的表格中进行数据汇总和聚合,以便更方便进行分析的表格。它可以将数据从行转换为列,并以更有意义的方式展示数据。

在SQL中,我们可以使用PIVOT运算符创建透视表。该运算符可以根据指定的列对数据进行汇总,并以表格的形式呈现结果,使数据更易于理解和分析。透视表为我们提供了一种灵活且直观的方式来汇总和展示数据,从而帮助我们更好地理解数据的关系和趋势。

例如:

SELECT 
  customer_id, 
  [1] AS Product1, 
  [2] AS Product2, 
  [3] AS Product3, 
  [4] AS Product4, 
  [5] AS Product5
FROM (
  SELECT 
    customer_id, 
    product_id, 
    order_quantity
  FROM orders
) p
PIVOT (
  SUM(order_quantity)
  FOR product_id IN ([1], [2], [3], [4], [5])
) AS pvt;

在上面的示例中,查询使用PIVOT运算符按产品ID旋转数据,每个客户都有一个列。SUM函数用于计算每个客户订购的每种产品的总数量。

子查询p用于从orders表中提取必要的列。然后将PIVOT运算符应用于子查询,使用SUM函数计算每个客户订购的每种产品的总数量。FOR子句指定了透视列(在本例中为product_id),而IN子句指定了要透视的值(在本例中为[1]、[2]、[3]、[4]、[5])。

查询的结果是一个透视表,显示了每个客户订购的每种产品的总数量,每种产品都有一列,每个客户都有一行。

透视表也可以用于许多其他情况,例如汇总销售数据、分析调查结果等。通过使用透视表,您可以使SQL查询更加强大和灵活。

5. 子查询

SQL中的子查询是用于从一个或多个表中检索数据的嵌套查询,子查询的结果在主查询中使用。它们可用于过滤、排序和分组数据,并可分类为单行或多行子查询。子查询括在括号中,可以在SQL语句的各个部分中使用,例如SELECT、FROM、WHERE和HAVING子句。

例如;有两个名为employees和salaries的表。employees表包含以下列:employee_id、first_name、last_name和department_id。salaries表包含以下列:employee_id、salary和salary_date。您想要找到每个部门工资最高的员工的姓名。为此,您可以使用子查询查找每个部门的最高工资,然后将结果与employees和salaries表连接以获取具有该工资的员工的姓名。

下面的查询使用子查询查找每个部门的最高工资。首先执行子查询并返回包含每个部门最高工资的结果集。然后,主查询将employees和salaries表与子查询的结果连接,以获取每个部门工资最高的员工的姓名。

SELECT 
  e.first_name, 
  e.last_name, 
  e.department_id, 
  s.salary
FROM 
  employees e 
  INNER JOIN salaries s ON e.employee_id = s.employee_id 
  INNER JOIN (
    SELECT 
      department_id, 
      MAX(salary) AS max_salary
    FROM 
      salaries
    GROUP BY 
      department_id
  ) m ON s.department_id = m.department_id AND s.salary = m.max_salary;

使用INNER JOIN子句将employees和salaries表连接起来,使用employee_id列作为连接键。使用department_id列将子查询连接到主查询,并使用salary列匹配每个部门的最高工资。

查询的结果是一个表格,显示每个部门工资最高的员工的姓名及其部门ID和工资。

6. 交叉连接

交叉连接是一种连接操作,用于返回两个或多个表的所有可能行组合,而不需要连接条件。它在生成测试数据或需要获取多个表格所有可能组合的计算时非常有用。然而,由于交叉连接可能会产生高计算成本和庞大的结果集,因此在使用时需要谨慎考虑其影响,并确保结果集的大小符合预期。通常情况下,应优先考虑使用其他类型的连接操作,如内连接、外连接或等值连接,以更有效地获取所需的数据。

在下面的示例中,有两个名为customers和orders的表。customers表包含以下列:customer_id、customer_name和city。orders表包含以下列:order_id、customer_id和order_date。您想要找到每个客户在每个城市下单的总数。为此,您可以使用交叉连接生成一个结果集,将每个客户与每个城市组合,然后将结果与orders表连接以获取每种组合的订单数量。

SELECT 
  c.customer_id, 
  c.customer_name, 
  c.city, 
  COUNT(o.order_id) AS order_count
FROM 
  customers c 
  CROSS JOIN (
    SELECT DISTINCT 
      city
    FROM 
      customers
  ) cities 
  LEFT JOIN orders o ON c.customer_id = o.customer_id
WHERE 
  c.city = cities.city
GROUP BY 
  c.customer_id, 
  c.customer_name, 
  c.city;

示例中,查询使用交叉连接生成一个结果集,该结果集将每个客户与每个城市组合在一起。交叉连接首先执行,返回一个包含每个客户和城市的每个组合的结果集。然后,主查询使用左连接将交叉连接的结果与orders表连接,以确保即使客户没有下订单也包括所有客户在结果中。

WHERE子句用于过滤结果,仅包括客户所在城市与交叉连接中的城市匹配的行。这确保了结果仅显示每个客户在其各自城市中的订单数量。

GROUP BY子句用于按客户ID、客户名称和城市分组结果。COUNT()函数用于计算每个客户在每个城市中的订单数量。

查询的结果是一个表格,显示了每个客户在每个城市中下达的订单总数。

7. 临时表

SQL中的临时表是在执行SQL语句或事务期间创建和使用的表。它们存储在内存或磁盘上,并在创建它们的会话结束或不再需要时自动删除。临时表通常用于存储中间结果,或将复杂查询分解为更小、更易管理的部分。

它们可以使用CREATE TEMPORARY TABLE语句创建,并像常规表一样使用SQL命令(如SELECT、INSERT、UPDATE和DELETE)进行操作。临时表可以非常有用,用于优化复杂查询并提高性能,因为它们可以帮助减少需要在任何给定时间处理的数据量。

假设有一个名为sales的表,其中包含以下列:date、product、category和sales_amount。您想创建一个报告,显示过去一年每个月每个类别的总销售额。为此,您可以使用一个临时表来创建每个月销售数据的摘要,然后将临时表与sales表连接,以获取每个类别的总销售额。

首先,您可以使用CREATE TEMPORARY TABLE语句创建临时表:

CREATE TEMPORARY TABLE monthly_sales_summary (
  month DATE,
  category VARCHAR(50),
  total_sales DECIMAL(10,2)
);

此语句创建了一个名为monthly_sales_summary的临时表,其中包含三列:month、category和total_sales。month列的类型为DATE,category列的类型为VARCHAR(50),total_sales列的类型为DECIMAL(10,2)。

接下来,使用INSERT INTO语句将摘要数据填充到临时表中:

INSERT INTO monthly_sales_summary (month, category, total_sales)
SELECT 
  DATE_TRUNC('month', date) AS month,
  category,
  SUM(sales_amount) AS total_sales
FROM 
  sales
WHERE 
  date >= DATE_TRUNC('year', CURRENT_DATE) -- sales from the past year
GROUP BY 
  DATE_TRUNC('month', date),
  category;

此语句使用DATE_TRUNC函数将date列截断到月份级别,按月份和类别分组销售数据。此查询的结果插入到monthly_sales_summary表中,该表现在包含每个月销售数据的摘要。

最后,可以将临时表与sales表连接起来,以获取每个类别的总销售额:

SELECT 
  s.category, 
  mss.month, 
  mss.total_sales
FROM 
  sales s 
  JOIN monthly_sales_summary mss 
    ON s.category = mss.category 
    AND DATE_TRUNC('month', s.date) = mss.month
WHERE 
  s.date >= DATE_TRUNC('year', CURRENT_DATE) -- sales from the past year
ORDER BY 
  s.category, 
  mss.month;

此语句将sales表与monthly_sales_summary表连接在category和month列上,并从临时表中选择category、month和total_sales列。WHERE子句用于过滤结果,仅包括过去一年的销售数据,ORDER BY子句用于按类别和月份对结果进行排序。

查询的结果是一个表格,显示了过去一年每个月每个类别的总销售额。

8. 具体化视图

SQL中的具体化视图是存储为物理表的预计算结果集。它们基于SQL查询创建和维护,并用于提高频繁执行查询的性能。具体化视图可以按计划或按需刷新,以确保数据是最新的。当针对具体化视图执行查询时,结果集从物理表中检索,而不是从原始表中计算。

这可以提升性能,特别是对于涉及联接或聚合函数的复杂查询。具体化视图通常用于数据仓库和业务智能应用程序中,在这些应用程序中,它们可以帮助加速报告和仪表板。

例如,有一个名为sales的大型表,其中包含以下列:date、product、category和sales_amount。您想创建一个报告,显示过去一年每个月每个类别的总销售额。但是,直接在sales表上运行此查询会很慢,因为它包含数百万行。为了加快查询速度,可以创建一个物化视图,按月份和类别汇总销售数据。

要创建物化视图,可以使用CREATE MATERIALIZED VIEW语句,如下所示:

CREATE MATERIALIZED VIEW monthly_sales_summary AS 
SELECT 
  DATE_TRUNC('month', date) AS month,
  category,
  SUM(sales_amount) AS total_sales
FROM 
  sales
WHERE 
  date >= DATE_TRUNC('year', CURRENT_DATE) -- sales from the past year
GROUP BY 
  DATE_TRUNC('month', date),
  category;

此语句创建了一个名为monthly_sales_summary的物化视图,其中包含每个月和类别的销售数据摘要。SELECT语句与前面示例中用于创建临时表的语句相同,但是不使用临时表,而是将结果存储在物化视图中。

物化视图与表类似,因为它们将数据存储在磁盘上,但是在基础数据更改时会自动更新。您可以使用REFRESH MATERIALIZED VIEW语句手动刷新物化视图,也可以使用cron作业或其他调度工具设置定期刷新。

创建物化视图后,可以像查询其他表一样查询它:

SELECT 
  category, 
  month, 
  total_sales
FROM 
  monthly_sales_summary
ORDER BY 
  category, 
  month;

此语句从monthly_sales_summary物化视图中选择category、month和total_sales列,并按类别和月份对结果进行排序。

在这种情况下使用物化视图的优点在于,它允许您预计算和存储摘要数据,从而减少运行查询所需的时间。物化视图特别适用于经常运行并需要对大型数据集进行复杂计算的报告。但是,它们也有一些限制,例如它们可能占用大量磁盘空间,并且在基础数据更改时可能无法立即更新。

结语

掌握高级SQL技术,如窗口函数、CTE、聚合函数、透视表、子查询、交叉连接、临时表和物化视图,可以帮助您更有效地处理复杂的数据分析任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1054526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Zero-Shot Learning by Harnessing Adversarial Samples 理论 代码解读

《Zero-Shot Learning by Harnessing Adversarial Samples》基于对抗样本的零样本学习 该论文要解决的问题: 减轻了传统图像增强技术中固有的语义失真问题。我们希望我们的实验研究将有助于理解单标签监督和语义属性监督在模型行为上的差异,并为开发更…

10.01

服务器 #include<myhead.h> //键盘输入事件 int keybord_events(fd_set readfds) {char buf[128] "";int sndfd -1; //从终端获取一个文件描述符&#xff0c;发送数据给该文件描述符对应的客户端bzero(buf, sizeof(buf));int res scanf("…

Junit的常用操作

注:本篇文章讲解的是junit5 目录 Juint是什么 Juint需要导入的依赖 Juint常用注解 Junit执行顺序 参数化 断言 测试套件 Juint是什么 Juint 是 Java 的一个单元测试框架. 也是回归测试框架. 使用 Junit 能让我们快速的完成单元测试。 注意&#xff1a;Junit 测试也是程序…

网络安全渗透测试工具之skipfish

网络安全渗透测试工具skipfish介绍 在数字化的时代,Web 应用程序安全成为了首要任务。想象一下,您是一位勇敢的安全冒险家,迎接着那些隐藏在 Web 应用程序中的未知风险。而在这个冒险之旅中,您需要一款强大的工具来帮助您发现漏洞,揭示弱点。而这个工具就是 Skipfish。 …

【Android】安卓手机系统内置应用安装失败解决方案

现有的闲置手机有个内置app可老旧了&#xff0c;没有开发者维护&#xff0c;于是问题不断&#xff0c;影响了体验&#xff0c;后来在网上查找发现有它的新版本&#xff0c;想要更新却没有自动更新&#xff08;后台服务断开了&#xff09;&#xff0c;有类似的想法可以来这里了解…

国庆创作周 组播《第十二课》

国庆创作周《第十二课》图解

实现单行/多行文本溢出

在日常开发展示页面&#xff0c;如果一段文本的数量过长&#xff0c;受制于元素宽度的因素&#xff0c;有可能不能完全显示&#xff0c;为了提高用户的使用体验&#xff0c;这个时候就需要我们把溢出的文本显示成省略号。 一. 单行文本溢出 即文本在一行内显示&#xff0c;超出…

Blued引流脚本

于多数人来说&#xff0c;引流都是一个比较困难的操作&#xff0c;因为流量不会听你的。所以任何人在网上做生意&#xff0c;或者开一个实体店&#xff0c;都会为流量而发愁&#xff0c;其实对于流量的吸引来说&#xff0c;我们越是刻意为之&#xff0c;可能所获得的效果也越不…

基于Java的在线听歌平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

从 0 到 1 ,手把手教你编写《消息队列》项目(Java实现) —— 介绍项目/ 需求分析

文章目录 一、消息队列是什么&#xff1f;二、需求分析结构解析功能解析规则解析绑定关系交换机类型消息应答 三、持久化存储四、网络通信提供的API复用TCP连接 五、消息队列概念图 一、消息队列是什么&#xff1f; 消息队列 (Message Queue, MQ)就是将阻塞队列这一数据结构提取…

国庆作业2

select实现服务器并发 代码&#xff1a; #include <myhead.h>#define ERR_MSG(msg) do{\printf("%d\n",__LINE__);\perror(msg);\ }while(0)#define PORT 8888#define IP "192.168.1.5"int main(int argc, const char *argv[]) {//创建流式套接字…

格拉姆角场GAF将时序数据转换为图像并应用于东南大学轴承故障诊断(Python代码,CNN模型)

1.运行效果&#xff1a;格拉姆角场GAF将时序数据转换为图像并应用于东南大学轴承故障诊断&#xff08;Python代码&#xff0c;CNN模型&#xff09;_哔哩哔哩_bilibili 环境库 只要tensorflow版本大于等于2.4.0即可运行 2.GAF的内容 GAF是一种用于时间序列数据可视化和特征提…

崇州街子古镇中秋国庆热闹非凡

今天&#xff08;国庆节日&#xff09;下午约4点钟&#xff0c;笔者实在耐不住寂寞&#xff0c;走出寄居养老的成都市崇州街子古镇青城神韵小区&#xff0c;去到国家AAAA级旅游景区那古色古香的街子古镇街道&#xff0c;旨在要亲身感受一下今年这里过双节&#xff0c;气氛究竟会…

28294-2012 钢渣复合料 课堂随笔

声明 本文是学习GB-T 28294-2012 钢渣复合料. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了混凝土用钢渣复合料的术语和定义、原材料组成及要求、强度等级、技术要求、试验方 法、检验规则、包装、标识、运输与贮存。 本标准…

WinHex数据恢复方法(误删后没覆盖)

winhex永远滴神&#xff01;winhex永远滴神&#xff01;winhex永远滴神&#xff01; md&#xff0c;安卓手机插u盘&#xff0c;改个文件夹名竟然把整个文件夹搞没了&#xff01;于是我赶紧查怎么恢复&#xff0c;然后依次找到并试用了diskgenus&#xff08;410RMB&#xff09;、…

信息安全:使用程序编写基于密钥的加密方式

目录 前言RSA算法代码实现设计思路结果示意 Diffie-Hellman算法代码实现设计思路结果示意 前言 信息安全是计算机科学的一个重要分支&#xff0c;它涉及到保护信息的机密性、完整性和可用性。信息加密是信息安全的一种常用手段&#xff0c;它通过使用一些数学算法和密钥&#…

P1525 [NOIP2010 提高组] 关押罪犯(并查集)

[NOIP2010 提高组] 关押罪犯 题目描述 S 城现有两座监狱&#xff0c;一共关押着 N N N 名罪犯&#xff0c;编号分别为 1 − N 1-N 1−N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久&#xff0c;如果客观条件具备则随时可能爆发冲突。我们用“怨气值”&#x…

编程每日一练(多语言实现)基础篇:满足abcd=(ab+cd)^2的数 (增加Go语言实现)

文章目录 一、实例描述二、技术要点三、代码实现3.1 C 语言实现3.2 Python 语言实现3.3 Java 语言实现3.4 JavaScript 语言实现3.5 Go 语言实现 一、实例描述 假设 abcd 是一个四位整数&#xff0c;将它分成两段&#xff0c;即 ab 和 cd&#xff0c;使之相加求和后再平方。求满…

linux入门---信号量

什么是信号量 信号量的本质是一个计数器&#xff0c;通常用来表示公共资源中资源数量多少&#xff0c;公共资源是指可以被多个进程同时访问的资源&#xff0c;访问没有被保护的公共资源时可能出现数据不一致的问题&#xff0c;比如说一个进程对公共资源执行一些写操作&#xf…

Python 数据分析与挖掘(一)

Python 数据分析与挖掘&#xff08;数据探索&#xff09; 数据探索 1.1 需要掌握的工具&#xff08;库&#xff09; 1.1.1 Nump库 Numpy 提供多维数组对象和各种派生对象&#xff08;类矩阵&#xff09;&#xff0c;利用应用程序接口可以实现大量且繁琐的数据运算。可以构建…