当前位置: 首页 > news >正文

SQL组合查询与分组过滤深度解析:从原理到LeetCode实战

SQL组合查询与分组过滤深度解析:从原理到LeetCode实战

在数据分析和后端开发中,SQL是必备技能。无论是处理用户数据还是构建报表,组合查询(UNION)和分组过滤(GROUP BY + HAVING)都是高频操作。本文通过原理剖析和LeetCode实战,帮你彻底掌握这些核心知识点,同时串联JavaScript、Java、C++、Python、Go等语言中的数据处理思维,提升你的数据库编程效率。

一、UNION与UNION ALL:组合查询的两种方式

UNION用于合并两个或多个SELECT语句的结果集,默认会去除重复行。使用时需注意:所有SELECT语句选择的列数必须相同,对应列的数据类型需兼容,且列序必须一致。例如,从Customers和Suppliers表中分别查询德国地区的城市和国家:

SELECT City, Country FROM Customers WHERE Country='Germany'
UNION
SELECT City, Country FROM Suppliers WHERE Country='Germany'
ORDER BY City;

最佳实践:若想保留重复值,使用UNION ALL,它比UNION更快(省去去重步骤)。在JavaScript、Java、C++、Python、Go等语言中处理数据时,类似去重操作(如Python的set()或Java的Stream.distinct())也需权衡性能。

常见场景:合并不同来源的同类数据,如将多个分表的数据汇总展示。若需标记数据来源,可添加常量列:

SELECT 'Customer' AS Type, ContactName, City, Country FROM Customers
UNION
SELECT 'Supplier', ContactName, City, Country FROM Suppliers;
在这里插入图片描述

二、GROUP BY与HAVING:分组聚合的黄金搭档

GROUP BY将数据按指定列分组,配合聚合函数(如COUNT、SUM、AVG)进行统计。例如,统计每个国家的客户数:

SELECT COUNT(CustomerID), Country FROM Customers
GROUP BY Country
ORDER BY COUNT(CustomerID) DESC;

⚠️ 关键约束:WHERE无法与聚合函数一起使用,因为它是在分组前过滤行。此时需用HAVING子句,它允许在分组后对聚合结果进行筛选:

SELECT column1, aggregate_function(column2)
FROM table_name
GROUP BY column1
HAVING condition(可使用聚合函数);

实战对比:在Python的pandas中,groupby()后可用filter()实现类似HAVING功能;在Java的Stream API中,collect(Collectors.groupingBy())后配合filter()也能达到相同效果。理解SQL的HAVING逻辑,有助于跨语言迁移数据处理思维。

三、LeetCode重点题型实战:连接与聚合

LeetCode SQL题库中,连接与聚合是核心考点。以下精选5道题,覆盖简单到中等难度,帮你巩固UNION、GROUP BY、自连接等技巧。

1. 1661. 每台机器的进程平均运行时间

该题考察ROUND函数与聚合分组。ROUND(number, digits)用于四舍五入保留小数位数。核心代码:

# Write your MySQL query statement below
#第一个想法:是否将这个表自链接,形成开始和结束和时间戳来
select a.machine_id, a.process_id, a.timestamp, b.machine_id, b.process_id, b.timestamp
from Activity a, Activity b
where a.process_id=b.process_id and a.activity_type='start' and
b.activity_type='end' and a.machine_id=b.machine_id;
#使用分组来进行机器的总体平均
#本题答案
select a.machine_id, round(avg(b.timestamp-a.timestamp),3) as processing_time
from Activity a, Activity b
where a.process_id=b.process_id and a.activity_type='start' and
b.activity_type='end' and a.machine_id=b.machine_id
group by a.machine_id;
在这里插入图片描述在这里插入图片描述

2. 577. 员工奖金

考察左连接(LEFT JOIN)和NULL处理。当员工无奖金时,需用IFNULL或COALESCE填充默认值:

#直接使用左连接来连接奖金
select Employee.name, Bonus.bonus
from Employee
left join Bonus on Employee.empId = Bonus.empId
where Bonus.bonus<1000 or Bonus.bonus is null;
在这里插入图片描述

3. 1280. 学生们参加各科测试的次数

本题需要理解笛卡尔积(CROSS JOIN),它生成所有可能的组合,再通过左连接匹配实际数据。例如:

SELECT t1.emp_id, t1.emp_name, t1.hire_date, t2.dept_name
FROM employees AS t1
CROSS JOIN departments AS t2;

补充:IFNULL(expression, alt_value)用于处理NULL值,若expression为NULL则返回alt_value。这在数据填充中非常实用:

# Write your MySQL query statement below
SELECT
s.student_id, s.student_name, sub.subject_name, IFNULL(grouped.attended_exams, 0) AS attended_exams
FROM
Students s
CROSS JOIN
Subjects sub
LEFT JOIN (
SELECT student_id, subject_name, COUNT(*) AS attended_exams
FROM Examinations
GROUP BY student_id, subject_name
) grouped
ON s.student_id = grouped.student_id AND sub.subject_name = grouped.subject_name
ORDER BY s.student_id, sub.subject_name;
在这里插入图片描述在这里插入图片描述

4. 570. 至少有5名直接下属的经理

经典错误:在WHERE中使用聚合函数(如COUNT)会导致失败,因为WHERE在聚合前执行。正确做法是使用HAVING或自连接。自连接示例:

# Write your MySQL query statement below
#分组来收集经理id
select managerID, count(managerID)
from Employee
where count(managerID) > 5
group by managerID;
# Write your MySQL query statement below
#分组来收集经理id
select b.name
from Employee a, Employee b
where a.managerID=b.id
group by a.managerID
having count(a.managerID)>=5;
在这里插入图片描述

5. 1934. 确认率

本题综合了左连接、聚合和条件统计,适合练习复杂业务逻辑:

# Write your MySQL query statement below
#其中AVG(b.action='confirmed')等价于SUM(IF(action = 'confirmed', 1, 0)) / COUNT(action)
SELECT a.user_id, ROUND(IFNULL(AVG(b.action='confirmed'), 0), 2) AS confirmation_rate
FROM Signups AS a
LEFT JOIN Confirmations AS b
ON a.user_id = b.user_id
GROUP BY a.user_id;
在这里插入图片描述[AFFILIATE_SLOT_1]

四、常见错误与性能调优

在组合查询和分组过滤中,新手常犯以下错误:

  • 列数不匹配:UNION时各SELECT列数不一致,导致语法错误。
  • HAVING与WHERE混淆:记住WHERE过滤行,HAVING过滤组。
  • 忽视索引:GROUP BY和ORDER BY列建议建索引,否则大数据量下性能堪忧。

最佳实践

  • 使用EXPLAIN分析查询计划,定位瓶颈。
  • 在Python、Java、C++、Go等语言中调用SQL时,尽量将过滤条件提前,减少数据传输。
  • 对于复杂聚合,考虑使用窗口函数(如ROW_NUMBER)替代子查询,提升可读性。
[AFFILIATE_SLOT_2]

总结

本文从UNION/UNION ALL的语法细节出发,深入讲解了GROUP BY与HAVING的分组过滤机制,并通过5道LeetCode实战题巩固了连接、聚合和自连接等核心技能。掌握这些知识点后,你不仅能高效处理SQL查询,还能将类似的数据处理逻辑迁移到JavaScript、Java、C++、Python、Go等语言中,实现跨平台的数据分析能力。勤加练习,你也能成为SQL高手!

http://www.jsqmd.com/news/756018/

相关文章:

  • Windows 11任务栏透明化终极指南:用TranslucentTB打造个性化桌面
  • 2026最权威的十大AI论文方案实测分析
  • 给娃讲编程:用ICode竞赛里的嵌套for循环,画个会变大的‘贪吃蛇’(Python实战)
  • 从‘剪坏’到‘剪好’:手把手教你用Torch-Pruning完成DeepLabV3+剪枝后的精度恢复训练
  • SAP BAPI搞不定凭证抬头字段?试试这个FB02+BDC的“组合拳”方案
  • Controlnet QR Code Monster v2灰色背景技巧:让二维码与图像无缝融合
  • 【软件使用】向日葵网络连接错误
  • ORAS实战案例:在真实项目中如何应用容器镜像管理
  • 别再只用开关阀了!用Matrix高频阀的PWM/PFM技术,轻松实现低成本比例控制
  • 5分钟搞定NCM加密:ncmdump工具终极操作指南
  • mirrors/unsloth/llama-3-8b-bnb-4bit教育应用:安全微调与内容过滤实践
  • Lattice MachXO4 FPGA低功耗特性与嵌入式应用解析
  • Seraphine终极指南:5分钟掌握英雄联盟智能助手,免费提升游戏胜率
  • 别再乱用create_clock了!聊聊SDC约束中时钟定义的5个常见误区与避坑指南
  • 2025最权威的五大AI写作方案推荐
  • 智能体支付平台架构设计:从支付即服务到高可用实战
  • 如何用Python实现剪映自动化:JianYingApi技术解析与实践指南
  • csp信奥赛C++高频考点专项训练之字符串 --【字符统计与大小写转换】:统计数字字符个数
  • IDM-VTON实战教程:一步步教你构建个性化虚拟试穿应用
  • 30天无限循环:JetBrains IDE试用期重置终极方案
  • 将OpenClaw智能体工作流接入Taotoken以统一调用多种大模型
  • 别再只盯着CCLK了:K7 FPGA远程更新时,STARTUPE2的CFGMCLK和EOS信号还能这么用
  • 5个步骤,用ContextMenuManager彻底净化你的Windows右键菜单
  • 从零到一:SillyTavern如何让AI对话与图像生成变得如此简单
  • NVIDIA Profile Inspector完整配置指南:快速解决95%游戏优化问题
  • AutoSar Dem模块与UDS 0x19服务联调:手把手教你配置DTC状态掩码与快照数据
  • 3个智能突破:Seraphine如何重新定义你的英雄联盟游戏体验
  • 如何快速提升团队二维码设计效率:Controlnet QR Code Monster v2 终极指南
  • Stark Shield:微服务架构下的统一安全基础设施设计与实践
  • 六音音源修复版:让洛雪音乐重获新生!新手必看避坑指南