尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

SQL查询优化:IN、EXISTS、JOIN与聚合函数详解

SQL查询优化:IN、EXISTS、JOIN与聚合函数详解 摘要本文详细介绍了SQL查询中常用的IN与EXISTS运算符的区别、各种JOIN连接查询的使用场景、嵌套子查询的编写方法以及聚合函数的基本使用和嵌套应用。通过对比分析和实例演示帮助读者深入理解这些SQL核心概念提升查询编写和优化能力。前言阅读指南本文旨在为不同层次的SQL学习者提供全面的查询优化知识体系。无论您是SQL初学者还是希望提升查询性能的开发人员本文都将帮助您深入理解SQL核心概念及其应用场景。目标读者SQL初学者希望系统学习IN/EXISTS、JOIN、子查询和聚合函数等基础概念中级开发者需要优化现有查询理解不同查询方式的性能差异数据库管理员希望掌握查询优化技巧提升数据库性能数据分析师需要编写高效的数据提取和聚合查询先验知识要求为了更好地理解本文内容建议读者具备以下基础知识基本的SQL语法SELECT、FROM、WHERE等了解关系型数据库的基本概念表、行、列熟悉简单的数据查询操作了解主键、外键等基本数据库约束概念章节概览与学习路径本文按照从基础到应用的逻辑顺序组织内容建议按以下顺序阅读一、IN 与 EXISTS 的区别深入对比两种运算符的语义、性能差异和使用场景帮助您根据数据规模选择合适的查询方式。二、连接查询JOIN系统讲解INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN四种连接类型通过Mermaid流程图和实战示例直观展示不同JOIN的结果集差异。三、嵌套子查询涵盖WHERE、FROM、UPDATE、DELETE等子句中的子查询应用提供多个实战示例和性能优化建议。四、聚合函数的使用介绍COUNT、SUM、AVG、MAX、MIN等聚合函数的基本用法以及WHERE与HAVING子句的区别。五、聚合函数的嵌套使用深入探讨聚合函数在复杂查询中的应用包括分组过滤和性能优化。六、总结与参考资料汇总各章节核心要点提供官方文档和权威技术资源链接方便进一步学习。学习建议动手实践建议在本地数据库或在线SQL练习平台如SQL Fiddle、DB Fiddle中运行文中的示例代码。对比分析对于IN vs EXISTS、不同JOIN类型等对比性内容建议创建测试数据并亲自验证结果差异。性能测试对于涉及性能优化的部分如子查询优化可以在自己的数据环境中进行性能测试。循序渐进如果对某个概念感到困惑可以先跳过继续阅读后续内容待整体理解后再回头深入。通过本文的学习您将能够准确区分IN和EXISTS的使用场景并做出性能最优的选择根据业务需求选择最合适的JOIN类型编写高效、可维护的嵌套子查询正确使用聚合函数进行数据统计和分析识别和优化常见的SQL性能瓶颈现在让我们开始深入学习SQL查询优化的核心知识。一、IN 与 EXISTS 的区别IN和EXISTS是SQL查询中常用的两种运算符它们在语义和使用方式上有明显区别。1.1 IN运算符IN是一个集合运算符语法形式为a IN {a,c,d,s,d....}。在这个运算中前面是一个元素后面是一个集合集合中的元素类型必须和前面的元素类型一致。IN运算用在语句中时它后面带的SELECT语句一定是选一个字段而不是SELECT *。例如要判断某班是否存在一个名为小明的学生可以使用IN运算小明 IN (SELECT sname FROM student)这样(SELECT sname FROM student)返回的是一个全班姓名的集合IN用于判断小明是否为此集合中的一个数据。1.2 EXISTS运算符EXISTS是一个存在判断如果后面的查询中有结果则EXISTS为真否则为假。例如EXISTS (SELECT * FROM student WHERE sname小明)1.3 性能对比与优化这两个函数在功能上相似但由于优化方案的不同通常NOT EXISTS要比NOT IN快因为NOT EXISTS可以使用结合算法而NOT IN就不行了。而EXISTS则不如IN快因为这时候IN可能更多的使用结合算法。示例对比SELECT * FROM 表A WHERE EXISTS(SELECT * FROM 表B WHERE 表B.id表A.id) -- 这句相当于 SELECT * FROM 表A WHERE id IN (SELECT id FROM 表B)对于表A的每一条数据都执行SELECT * FROM 表B WHERE 表B.id表A.id的存在性判断如果表B中存在表A当前行相同的id则EXISTS为真该行显示否则不显示。使用建议EXISTS适合内大外小的查询IN适合内小外大的查询。1.4 官方定义对比IN确定给定的值是否与子查询或列表中的值相匹配。EXISTS指定一个子查询检测行的存在。1.5 实例对比比较使用EXISTS和IN的查询。以下两个查询语义类似返回相同的信息-- 使用EXISTS USE pubs GO SELECT DISTINCT pub_name FROM publishers WHERE EXISTS (SELECT * FROM titles WHERE pub_id publishers.pub_id AND type business) GO-- 使用IN USE pubs GO SELECT DISTINCT pub_name FROM publishers WHERE pub_id IN (SELECT pub_id FROM titles WHERE type business) GO下面是任一查询的结果集pub_name ---------------------------------------- Algodata Infosystems New Moon Books (2 row(s) affected)1.6 逻辑含义总结EXISTS相当于存在量词表示集合存在也就是集合不为空只作用一个集合。例如EXIST P表示P不空时为真NOT EXIST P表示P为空时为真。IN表示一个标量和一元关系的关系。例如s IN P表示当s与P中的某个值相等时为真s NOT IN P表示s与P中的每一个值都不相等时为真。二、连接查询JOIN连接查询是SQL中用于从多个表中检索数据的重要技术。不同的SQL JOIN返回的结果集不一样。SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo FROM Persons INNER JOIN Orders ON Persons.Id_P Orders.Id_P ORDER BY Persons.LastName除了INNER JOIN内连接还可以使用其他几种连接类型JOININNER JOIN如果表中有至少一个匹配则返回行LEFT JOIN即使右表中没有匹配也从左表返回所有的行RIGHT JOIN即使左表中没有匹配也从右表返回所有的行FULL JOIN只要其中一个表中存在匹配就返回行注释INNER JOIN与JOIN是相同的为了更直观地理解这四种JOIN类型如何连接两个表并选取结果集下面通过Mermaid流程图展示Persons表和Orders表的连接关系flowchart TD subgraph Persons[Persons表] P1[Person A] P2[Person B] P3[Person C] end subgraph Orders[Orders表] O1[Order 1 Person A] O2[Order 2 Person A] O3[Order 3 Person B] end %% INNER JOIN - 只返回匹配的行 subgraph InnerJoin[INNER JOIN结果集] IJ1[Person A - Order 1] IJ2[Person A - Order 2] IJ3[Person B - Order 3] end %% LEFT JOIN - 返回左表所有行右表匹配的显示不匹配的显示NULL subgraph LeftJoin[LEFT JOIN结果集] LJ1[Person A - Order 1] LJ2[Person A - Order 2] LJ3[Person B - Order 3] LJ4[Person C - NULL] end %% RIGHT JOIN - 返回右表所有行左表匹配的显示不匹配的显示NULL subgraph RightJoin[RIGHT JOIN结果集] RJ1[Person A - Order 1] RJ2[Person A - Order 2] RJ3[Person B - Order 3] RJ4[NULL - Order 4] end %% FULL JOIN - 返回所有行匹配的显示不匹配的显示NULL subgraph FullJoin[FULL JOIN结果集] FJ1[Person A - Order 1] FJ2[Person A - Order 2] FJ3[Person B - Order 3] FJ4[Person C - NULL] FJ5[NULL - Order 4] end %% 连接关系展示 P1 --|匹配| O1 P1 --|匹配| O2 P2 --|匹配| O3 P3 --|无匹配| LJ4 O4[Order 4 无对应Person] --|无匹配| RJ4 %% 结果集说明 Persons --|INNER JOIN| InnerJoin Persons --|LEFT JOIN| LeftJoin Orders --|RIGHT JOIN| RightJoin Persons Orders --|FULL JOIN| FullJoin图例说明Persons表包含Person A、Person B、Person C三条记录Orders表包含Order 1属于Person A、Order 2属于Person A、Order 3属于Person B、Order 4无对应Person四条记录INNER JOIN只返回两个表都匹配的记录Person A-Order 1、Person A-Order 2、Person B-Order 3LEFT JOIN返回左表Persons所有记录右表匹配的显示订单信息不匹配的显示NULLPerson C显示为NULLRIGHT JOIN返回右表Orders所有记录左表匹配的显示人员信息不匹配的显示NULLOrder 4显示为NULLFULL JOIN返回两个表的所有记录匹配的显示对应信息不匹配的显示NULLPerson C和Order 4都显示为NULL简而言之就是你希望看到的结果集是怎样的。如两个表person和order连接如果你只想看到person中和order有联系的记录即满足order.id_p person.id的记录其他不匹配的全不显示就用INNER JOINLEFT JOIN就是在返回INNER JOIN的结果集的基础上返回左表person表中其余的记录这些显示的记录行所有与order表相关的栏为空因为它们不满足匹配关系同理RIGHT JOIN和FULL JOIN也有类似的逻辑2.1 实战示例员工与部门表 JOIN 查询为了更好地理解不同 JOIN 类型的实际效果我们使用一个具体的员工表employees和部门表departments进行演示。表结构与示例数据部门表 departmentsCREATE TABLE departments ( dept_id INT PRIMARY KEY, dept_name VARCHAR(50) ); INSERT INTO departments (dept_id, dept_name) VALUES (1, 技术部), (2, 销售部), (3, 人事部), (4, 财务部);员工表 employeesCREATE TABLE employees ( emp_id INT PRIMARY KEY, emp_name VARCHAR(50), dept_id INT, salary DECIMAL(10, 2) ); INSERT INTO employees (emp_id, emp_name, dept_id, salary) VALUES (101, 张三, 1, 8000.00), (102, 李四, 1, 7500.00), (103, 王五, 2, 6000.00), (104, 赵六, NULL, 5500.00), (105, 钱七, 5, 7000.00); -- 注意部门ID 5在departments表中不存在数据说明技术部dept_id1有2名员工张三、李四销售部dept_id2有1名员工王五人事部dept_id3和财务部dept_id4没有员工赵六emp_id104没有分配部门dept_id为NULL钱七emp_id105分配到了不存在的部门dept_id51. INNER JOIN内连接SQL 语句SELECT e.emp_id, e.emp_name, e.salary, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id ORDER BY e.emp_id;查询结果集emp_id | emp_name | salary | dept_name ------------------------------------- 101 | 张三 | 8000.00 | 技术部 102 | 李四 | 7500.00 | 技术部 103 | 王五 | 6000.00 | 销售部 (3 rows)解释INNER JOIN 只返回两个表中都有匹配的记录。赵六dept_id为NULL和钱七dept_id5在departments中不存在因为没有匹配的部门记录所以不显示。人事部和财务部因为没有员工也不显示。2. LEFT JOIN左连接SQL 语句SELECT e.emp_id, e.emp_name, e.salary, d.dept_name FROM employees e LEFT JOIN departments d ON e.dept_id d.dept_id ORDER BY e.emp_id;查询结果集emp_id | emp_name | salary | dept_name ------------------------------------- 101 | 张三 | 8000.00 | 技术部 102 | 李四 | 7500.00 | 技术部 103 | 王五 | 6000.00 | 销售部 104 | 赵六 | 5500.00 | NULL 105 | 钱七 | 7000.00 | NULL (5 rows)解释LEFT JOIN 返回左表employees的所有记录右表departments匹配的显示部门名称不匹配的显示NULL。赵六和钱七虽然部门不匹配但仍然显示在结果中对应的dept_name为NULL。3. RIGHT JOIN右连接SQL 语句SELECT e.emp_id, e.emp_name, e.salary, d.dept_name FROM employees e RIGHT JOIN departments d ON e.dept_id d.dept_id ORDER BY d.dept_id, e.emp_id;查询结果集emp_id | emp_name | salary | dept_name ------------------------------------- 101 | 张三 | 8000.00 | 技术部 102 | 李四 | 7500.00 | 技术部 103 | 王五 | 6000.00 | 销售部 NULL | NULL | NULL | 人事部 NULL | NULL | NULL | 财务部 (5 rows)解释RIGHT JOIN 返回右表departments的所有记录左表employees匹配的显示员工信息不匹配的显示NULL。人事部和财务部虽然没有员工但仍然显示在结果中对应的员工信息为NULL。4. FULL JOIN全连接SQL 语句SELECT e.emp_id, e.emp_name, e.salary, d.dept_name FROM employees e FULL JOIN departments d ON e.dept_id d.dept_id ORDER BY CASE WHEN e.emp_id IS NULL THEN 1 ELSE 0 END, e.emp_id, d.dept_id;查询结果集emp_id | emp_name | salary | dept_name ------------------------------------- 101 | 张三 | 8000.00 | 技术部 102 | 李四 | 7500.00 | 技术部 103 | 王五 | 6000.00 | 销售部 104 | 赵六 | 5500.00 | NULL 105 | 钱七 | 7000.00 | NULL NULL | NULL | NULL | 人事部 NULL | NULL | NULL | 财务部 (7 rows)解释FULL JOIN 返回两个表的所有记录匹配的记录显示对应信息不匹配的部分显示NULL。结果集包含了INNER JOIN 的结果3条匹配记录LEFT JOIN 独有的结果赵六、钱七共2条RIGHT JOIN 独有的结果人事部、财务部共2条四种 JOIN 类型对比总结JOIN 类型返回结果适用场景示例结果行数INNER JOIN只返回两个表都匹配的记录需要获取有关联的数据如有订单的客户3行LEFT JOIN返回左表所有记录 右表匹配记录不匹配为NULL需要获取左表所有数据无论右表是否有匹配如所有员工及其部门5行RIGHT JOIN返回右表所有记录 左表匹配记录不匹配为NULL需要获取右表所有数据无论左表是否有匹配如所有部门及其员工5行FULL JOIN返回两个表所有记录匹配的显示对应信息不匹配为NULL需要获取两个表的完整数据视图如员工与部门完整对应关系7行关键差异INNER JOIN只关心有对应关系的数据LEFT JOIN以左表为主右表为补充RIGHT JOIN以右表为主左表为补充FULL JOIN两个表的数据都要无论是否有对应关系在实际应用中LEFT JOIN 使用频率最高因为通常我们有一个主表如员工表需要关联其他表如部门表获取补充信息同时不希望丢失主表的任何记录。三、嵌套子查询嵌套子查询是指在一个查询父查询中嵌套另一个查询子查询。子查询可以出现在 SELECT、FROM、WHERE、HAVING 等子句中用于提供中间结果集或过滤条件。根据子查询与父查询的关联性可分为相关子查询引用了父查询中的列和非相关子查询独立执行。父查询可以是 SELECT、UPDATE、DELETE 语句。WHERE 子句中常用的运算符包括, , , , , 以及 IN, NOT IN, EXISTS, NOT EXISTS, ALL, ANY 等。3.1 实战示例一使用子查询进行数据过滤场景查询工资高于本部门平均工资的员工信息。SQL 语句-- 使用非相关子查询在 FROM 子句中 SELECT e.emp_id, e.emp_name, e.salary, e.dept_id, d.dept_name, dept_avg.avg_salary FROM employees e JOIN departments d ON e.dept_id d.dept_id JOIN ( -- 子查询计算每个部门的平均工资 SELECT dept_id, AVG(salary) AS avg_salary FROM employees WHERE dept_id IS NOT NULL GROUP BY dept_id ) dept_avg ON e.dept_id dept_avg.dept_id WHERE e.salary dept_avg.avg_salary ORDER BY e.dept_id, e.salary DESC;执行逻辑子查询(SELECT dept_id, AVG(salary) ... GROUP BY dept_id)首先独立执行生成一个临时结果集dept_avg包含每个部门的平均工资。主查询将employees表与departments表连接再与子查询结果dept_avg连接。WHERE e.salary dept_avg.avg_salary过滤出工资高于本部门平均工资的员工。注意事项性能当子查询结果集较大时连接操作可能较慢。可以考虑使用窗口函数如AVG() OVER (PARTITION BY dept_id)进行优化。NULL 值处理子查询中通过WHERE dept_id IS NOT NULL排除了未分配部门的员工避免因 NULL 值导致分组错误。可读性将子查询放在 FROM 子句中并为它起别名dept_avg可以提高 SQL 的可读性。3.2 实战示例二在 UPDATE 语句中使用子查询场景为销售部dept_id2所有员工的工资增加 10%但上限不超过公司最高工资的 80%。SQL 语句-- 使用子查询确定工资上限 UPDATE employees SET salary LEAST( salary * 1.1, -- 增加10% ( -- 子查询获取公司最高工资的80% SELECT MAX(salary) * 0.8 FROM employees WHERE dept_id IS NOT NULL ) ) WHERE dept_id 2; -- 仅针对销售部执行逻辑子查询(SELECT MAX(salary) * 0.8 FROM employees ...)首先执行一次计算出公司最高工资的 80% 作为上限值。主 UPDATE 语句对销售部dept_id 2的每一行计算salary * 1.1涨薪后与子查询返回的上限值取两者中较小者LEAST函数。最终更新符合条件的员工工资。注意事项单值要求在 SET 子句中使用子查询时子查询必须返回单个标量值一行一列。本例中MAX(salary) * 0.8返回一个数值。相关子查询风险如果子查询引用了正在更新的表且未妥善处理可能导致不可预测的结果或性能问题。本例中子查询独立于更新行是安全的。事务与锁UPDATE 语句通常会在事务中执行并可能锁定相关行。对于大数据量建议分批更新或评估性能影响。3.3 实战示例三在 DELETE 语句中使用子查询场景删除那些部门已被撤销在 departments 表中不存在的员工记录。SQL 语句-- 使用子查询识别无效部门ID DELETE FROM employees WHERE dept_id IS NOT NULL AND dept_id NOT IN ( -- 子查询获取所有有效的部门ID SELECT dept_id FROM departments );执行逻辑子查询(SELECT dept_id FROM departments)返回所有有效的部门 ID 列表。主 DELETE 语句删除employees表中那些dept_id不为 NULL 且不在有效部门 ID 列表中的记录。注意事项NOT IN 与 NULL如果子查询可能返回 NULL 值NOT IN的行为会变得复杂任何与 NULL 的比较结果都是 UNKNOWN。确保子查询结果集不包含 NULL或使用NOT EXISTS替代。性能对于大型表NOT IN子查询可能效率较低。如果 departments 表很大可考虑在 dept_id 上建立索引或使用NOT EXISTS配合相关子查询。数据安全执行 DELETE 前建议先用 SELECT 语句验证将要删除的记录或使用事务以便回滚。3.4 嵌套子查询的通用注意事项执行顺序通常子查询先于父查询执行非相关子查询但相关子查询需要为父查询的每一行执行一次可能导致性能问题。替代方案许多嵌套子查询可以用 JOIN 或窗口函数重写后者往往性能更优、可读性更好。可读性与维护过度嵌套会使 SQL 难以理解和调试。建议将复杂逻辑拆分为多个 CTECommon Table Expressions使用 WITH 子句或临时视图。测试在应用到生产环境前务必在测试环境中验证子查询的结果和性能。通过以上示例可以看出嵌套子查询是 SQL 中强大的工具合理使用可以解决复杂的数据操作需求但需注意其执行逻辑和潜在的性能影响。四、聚合函数的使用聚集函数和大多数其它关系数据库产品一样PostgreSQL支持聚集函数。一个聚集函数从多个输入行中计算出一个结果。比如我们有在一个行集合上计算COUNT(数目)、SUM(总和)、AVG(均值)、MAX(最大值)、MIN(最小值)的函数。例如我们可以用下面的语句找出所有低温中的最高温度SELECT MAX(temp_lo) FROM weather;结果max ----- 46 (1 row)如果我们想知道该读数发生在哪个城市可能会用SELECT city FROM weather WHERE temp_lo MAX(temp_lo); -- 错不过这个方法不能运转因为聚集函数MAX不能用于WHERE子句中。存在这个限制是因为WHERE子句决定哪些行可以进入聚集阶段因此它必需在聚集函数之前计算。不过我们可以用其它方法实现这个目的这里我们使用子查询SELECT city FROM weather WHERE temp_lo (SELECT MAX(temp_lo) FROM weather);结果city --------------- San Francisco (1 row)这样做是可以的因为子查询是一次独立的计算它独立于外层查询计算自己的聚集。聚集同样也常用于GROUP BY子句。比如我们可以获取每个城市低温的最高值SELECT city, MAX(temp_lo) FROM weather GROUP BY city;结果city | max -------------------- Hayward | 37 San Francisco | 46 (2 rows)这样每个城市一个输出。每个聚集结果都是在匹配该城市的行上面计算的。我们可以用HAVING过滤这些分组GROUP BY可以没有HAVING过滤但HAVING必须跟在GROUP BY的后面。SELECT city, MAX(temp_lo) FROM weather GROUP BY city HAVING MAX(temp_lo) 40;结果city | max -------------- Hayward | 37 (1 row)这样就只给出那些temp_lo值曾经有低于40度的城市。最后如果我们只关心那些名字以S开头的城市我们可以用SELECT city, MAX(temp_lo) FROM weather WHERE city LIKE S% GROUP BY city HAVING MAX(temp_lo) 40;五、聚合函数的嵌套使用语句中的LIKE执行模式匹配。理解聚集和SQL的WHERE和HAVING子句之间的关系非常重要。WHERE和HAVING的基本区别如下WHERE在分组和聚集计算之前选取输入行它控制哪些行进入聚集计算HAVING在分组和聚集之后选取输出行因此WHERE子句不能包含聚集函数因为试图用聚集函数判断那些行将要输入给聚集运算是没有意义的。相反HAVING子句总是包含聚集函数。当然你可以写不使用聚集的HAVING子句但这样做没什么好处因为同样的条件可以更有效地用于WHERE阶段。在前面的例子里我们可以在WHERE里应用城市名称限制因为它不需要聚集。这样比在HAVING里增加限制更加高效因为我们避免了为那些未通过WHERE检查的行进行分组和聚集计算。六、总结与参考资料6.1 核心要点总结本文详细介绍了SQL查询优化中的四个核心概念IN与EXISTS运算符、连接查询JOIN、嵌套子查询以及聚合函数的使用。以下是各主题的核心要点与选用原则1. IN 与 EXISTS 运算符IN运算符用于判断某个值是否在集合中适合内小外大的查询场景。EXISTS运算符用于检测子查询是否存在结果适合内大外小的查询场景。性能对比NOT EXISTS通常比NOT IN快因为可以使用结合算法而EXISTS在多数情况下不如IN快。选用原则当子查询结果集较小时使用IN结果集较大时使用EXISTS处理NULL值时需特别注意NOT IN的行为。2. 连接查询JOININNER JOIN只返回两个表都匹配的记录适用于需要获取有关联数据的场景。LEFT JOIN返回左表所有记录右表匹配记录不匹配为NULL适用于以左表为主表的查询。RIGHT JOIN返回右表所有记录左表匹配记录不匹配为NULL适用于以右表为主表的查询。FULL JOIN返回两个表所有记录匹配的显示对应信息不匹配为NULL适用于需要完整数据视图的场景。选用原则LEFT JOIN使用频率最高通常用于主表关联补充表且不希望丢失主表记录的场景。3. 嵌套子查询数据过滤在WHERE、FROM子句中使用子查询进行数据筛选和过滤。UPDATE/DELETE操作在数据修改语句中使用子查询确定操作范围。执行逻辑非相关子查询先于父查询执行相关子查询为父查询的每一行执行一次。选用原则优先考虑使用JOIN或窗口函数替代复杂嵌套子查询以提高性能对于简单过滤可使用子查询。4. 聚合函数基本函数COUNT、SUM、AVG、MAX、MIN等用于数据统计和分析。WHERE与HAVING区别WHERE在分组前过滤行不能使用聚合函数HAVING在分组后过滤组必须使用聚合函数。嵌套使用聚合函数可以嵌套在子查询中但不能直接在WHERE子句中使用。选用原则在WHERE子句中使用子查询替代聚合函数过滤在HAVING子句中使用聚合函数对分组结果进行筛选。6.2 参考资料MySQL官方文档 - 子查询https://dev.mysql.com/doc/refman/8.0/en/subqueries.html - 详细介绍了MySQL中子查询的语法、类型和使用场景。PostgreSQL官方文档 - 聚合函数PostgreSQL: Documentation: 18: 9.21. Aggregate Functions - 包含了PostgreSQL中所有聚合函数的详细说明和示例。SQL JOIN可视化指南Qlik Talend Cloud | Trusted, AI-Ready Data Integration Quality - 通过交互式图表直观展示各种JOIN类型的工作原理和结果集差异。SQL性能优化最佳实践SQL Indexing and Tuning e-Book for developers: Use The Index, Luke covers Oracle, MySQL, PostgreSQL, SQL Server, ... - 涵盖了SQL查询优化、索引使用、执行计划分析等高级主题。通过掌握这些SQL核心概念和优化技巧开发者可以编写出更高效、更易维护的数据库查询语句提升应用程序的整体性能。
返回列表