第五关:多表查询

第 5 级:多表查询 多表查询是 SQL 的一个非常重要的功能,它允许您检索和连接多个表中的数据。
下面详细解释多表查询。
1 、添加表(UNION) 添加表/Union:使用UNION子句合并两个结构相同的表。
默认情况下,UNION 子句会删除重复的数据,只留下一个。
如果需要保留重复数据,可以使用UNIONALL。
对表进行重复数据合并: select<列名 1 >,<列名 2 >,...from<表 1 >unionselect<列名 1 >,<列名 2 >,...from<表 2 >;保留重复数据合并: select<列名 1 >,<列名 2 >,...from<表 1 >unionselect<列名 1 >,<列名2 >,...来自<表2 >; UNION注意事项: 列数必须相同。
列类型必须一致。
ORDERBY 只能使用一次,通常放在最后一个 SELECT 语句之后。
2 . 表连接(JOIN) 表连接:关系数据库由多个表组成,每个表通过相关字段/列连接。
如果主表中的数据与其他表中的数据不匹配,则相应列中将输出空值。
交叉连接/笛卡尔积(CROSSJOIN):将一个表中的每一行数据与另一个表中的所有数据连接起来。
交叉连接是所有连接的基础,其他连接方式都是在交叉连接的基础上增加过滤条件。
交叉连接的写法: select<列名 1 >,<列名 2 >,...from<表 1 >as<表别名 1 >crossjoin<表 2 >as<表别名 2 >on<连接条件> CROSSJOIN 的应用: 由于输出结果较多,实际业务中不常使用。
INNERJOIN:查找同时存在于两个表中的数据。
内联接说明: select<列名1 >,<列名2 >,...from<表1 >as<表别名1 >innerjoin<表2 >as<表别名2 >on<联接条件> 左联接(LEFTJOIN):左表为主表,提取左表所有数据,右表只提取与左表联接相同的数据。
如果主表中的数据在辅助表中不可用,则辅助表中不存在的数据在连接过程中将显示为 NULL 值。
左联接说明: select<列名 1 >,<列名 2 >,...from<表 1 >as<表别名 1 >leftjoin<表 2 >as<表别名 2 >on<联接条件> 右联接(RIGHTJOIN):以右表为主表,提取右表中的所有数据,左表只检索与右表连接相同的数据。
如果主表中的数据在辅助表中不可用,则辅助表中不存在的数据在连接过程中将显示为 NULL 值。
右连接说明: select<列名1 >,<列名2 >,...from<表1 >as<表别名1 >rightjoin<表2 >as<表别名2 >on<连接条件> 全连接(FULLJOIN):MySQL不支持全连接。
全连接查询结果返回左表和右表的所有行。
如果一行与另一个表匹配,则这两行将被合并。
如果数据行与任何其他表都不匹配,则该行将用 NULL 值填充。
3 . 连接的执行顺序以及如何使用它们。
执行顺序:SQL在查询中,连接的执行顺序通常是从左到右,但您可以使用括号来更改执行顺序。
如何使用:如果您的业务中使用三个或更多表,则应该使用联接。
当您想要生成具有固定行数的表单,或者当您特别想要特定表中的所有数据时,请使用左/右联接。
在其他情况下,内部联接用于获取两个表的交集。
由于查询连接了多个表,因此我们需要将表别名添加到 SELECT 子句中的每个列名。
如果您只需要主表中的数据,不包括辅助表,只需在 WHERE 子句中的辅助表连接列中输入 =NULL 即可。
4 . CASE 表达式 CASE 表达式的使用方法: CASE 表达式相当于一个条件判断函数,满足条件时输出一个值,不满足条件时输出另一个值。
可与聚合函数和多个 CASE 表达式一起使用。
如果存在多种需要条件决策的情况,则应使用 CASE 表达式。
如何编写 CASE 表达式: casewhen<表达式>then<表达式>when<表达式>then<表达式>...else<表达式>end CASE 表达式注意事项: ELSE <表达式> 不能省略或写入。
即默认返回null值(不建议省略或不写以灌输书写习惯)。
END 语句不能省略。
CASE 语句可以出现在任何 SQL 子句中。

在SQL Server(Tableau中Join)中多表关联是否重复问题

在SQL Server中进行多表关联(连接表)时,数据是否重复取决于对应字段的值重复,与串并形式没有直接关系。
下面是典型的分析: 1 、串并联对迭代的影响 并联(图1 )只需要考虑从表和主表之间的一对多关系。
例如,主表A和副表B通过字段A.id=B.a_id关联。
如果B.a_id包含重复值(即一个A.id匹配多条B记录),则关联结果会因为副表重复而导致行数扩大。
重复性决策:如果副表中对应字段的值唯一,则结果不会重复;如果是一对多,结果会重复主表记录,重复次数等于副表中匹配记录的数量。
简而言之(图2 ),需要考虑后续表之间的字段关系。
例如表A→表B→表C,如果B表和C表对应的字段B.c_id有重复值,则C表的重复会进一步增加结果行数。
重复性决策:链中的每个一对多关系都可能导致累积重复。
例如,如果A表和B表是一对多(重复N次),B表和C表是一对多(重复M次),则最终结果将重复N×M次。
2 . 重复的主要决定因素是字段值的特殊性。
串联或并联无论哪种连接,重复都是由相关字段中值的重复决定的:如果所有相关字段在各自的表中都是唯一的(例如一对一的主键-外键关系),那么就不会出现结果重复。
如果相关字段存在一对多,由于多边表的记录扩展,结果会重复。
示例:表 A(唯一 id)与表 B(唯一 a_id)关联 → 没有重复结果。
A表(唯一id)与B表(重复a_id)关联→结果重复,次数等于a_id重复次数。
3 . 实际场景需要考虑的要点: 多表组合的累积效果。
组合起来,后续每个表的一对多关系都会叠加到之前的结果上。
例如:表A(1 项)→表B(3 项)→表C(2 项)→最终结果为1 ×3 ×2 =6 项。
需要使用DISTINCT或者调整关联逻辑(如子查询)以避免意外重复。
并行形式的独立性 在并行形式中,每个子表的迭代独立影响结果。
例如:表A(1 项)与表B(3 项)和表C(2 项)平行→结果为1 ×3 (B部分)+ 1 ×2 (C部分)= 5 项(非乘积关系)。
如果需要合并结果,则需要指定是删除还是保留重复项。
Tableau 中的处理建议 在 Tableau 中,您可以通过“数据源”页面调整关系类型(左联接、内联接等)或过滤重复项。
您可以使用计算字段来执行此操作。
在进行链式关联时,最好检查中间表的关联字段是否唯一,以避免多对多造成的数据爆炸。
4 、汇总并行表:重复性由副表对应字段的一对多决定。
由于副表重复,主表记录可能会扩展。
组合形式:重复是由所有关联字段一对多累加确定的,需要逐级检查后续表的字段唯一性。
一般原理:字段值的重复是根本原因,串联和并联仅影响重复的传播路径。
在设计关联时,应优先考虑确保关联字段的唯一性或为了逻辑合理性而明确接受重复。

如何处理SQL查询中的重复数据?通过去重和索引优化查询效率

SQL查询中处理重复数据的关键是选择合适的重复数据删除策略并与索引优化相结合。
下面是具体的优化方法和技巧: 1 、去重方式的选择 DISTINCT关键字适用于简单的去重场景,直接返回指定列的唯一组合。
从your_table 中选择DISTINCT 列1 、列2 ;优点:语法简洁,易于理解。
缺点:数据量大时需要全局排序,导致CPU和I/O开销较高,很容易成为性能瓶颈。
适用场景:数据量较小或快速原型开发。
GROUPBY子句通过分组实现重复数据删除,并支持聚合操作(如COUNT、SUM)。
SELECTcolumn1 ,column2 FROMyour_tableGROUPBYcolumn1 ,column2 ;优点:与 DISTINCT 逻辑类似,但某些数据库优化器的性能更好,特别是在需要聚合时。
缺点:聚合目标必须明确,否则可能会返回意想不到的结果。
适用场景:需要分组或聚合统计的查询。
ROW_NUMBER()窗口函数根据指定的规则为组内的行分配序号,并过滤掉序号为1 的行,实现复杂的去重。
WITHRankedDataAS(SELECTcolumn1 ,column2 ,ROW_NUMBER()OVER(PARTITIONBYcolumn1 ,column2 ORDERBYcolumn3 DESC)ASrnFROMyour_table)SELECTcolumn1 ,column2 FROMRankedDataWHERErn=1 ;优点:灵活定义重复条件(PARTITIONBY)和保留规则(ORDERBY),支持保留最新/最旧记录或多重限制。
缺点:语法复杂,必须与CTE结合使用。
适用场景:需要精确控制的保留记录复杂去重。
2 、索引优化策略 复合索引 在去重列(如column1 、column2 )上创建复合索引,以加快数据查找和比较的速度。
CREATEINDEXidx_nameONyour_table(列 1 ,列 2 );作用:减少全表扫描,提高DISTINCT和GROUPBY的性能。
覆盖索引 如果SELECT列表中的所有列都包含在索引中,则数据库可以直接从索引中获取数据,从而避免访问表数据。
示例:如果您的查询只涉及column1 和column2 ,并且索引已经覆盖了这两列,则不需要返回表。
效果:显着减少I/O操作,加快查询速度。
WHERE 和 JOIN 条件索引 在 WHERE 子句或 JOIN 条件涉及的列上创建索引,以加快数据过滤和连接速度。
示例: CREATEINDEXidx_whereONyour_table(where_column);CREATEINDEXidx_joinONyour_table(join_column);作用:减少重复数据删除的数据量,间接提高整体效率。
3 .方法选择和性能权衡数据量:对于小数据量,DISTINCT更可取;对于大量数据,GROUPBY 或 ROW_NUMBER() 更合适。
重复定义的复杂性:使用DISTINCT/GROUPBY进行简单重复;对于复杂的规则(例如保留最后一条记录),请使用 ROW_NUMBER()。
聚合需求:需要统计时选择GROUPBY;当不需要统计数据时,DISTINCT 更加简洁。
索引支持:无论您选择哪种方法,正确的索引都可以显着提高性能。
4 . 高级应用技能ROW_NUMBER() 保存多条记录:修改 WHERErn<=N 以保存每组中的前 N ​​条记录。
物理重复数据删除:结合 ROW_NUMBER() 和子查询来消除重复行。
WITHDuplicatesToDeleteAS(SELECTid,ROW_NUMBER()OVER(PARTITIONBYcolumn1 ,column2 ORDERBYidASC)ASrnFROMyour_table)DELETEFROMyour_tableWHEREidIN(SELECTidFROMDuplicatesToDeleteWHERErn>1 ); 5 .总结处理重复的SQL数据需要充分考虑数据量、定义重复的复杂性以及业务需求。
简单重复数据删除:DISTINCT 或 GROUPBY。
复杂重复数据删除:ROW_NUMBER()。
性能优化:复合索引、覆盖索引和WHERE/JOIN条件索引。
通过合理选择方法和优化索引,可以显着提高查询效率并保持数据质量。