day18(常见的面试题)

由于博客内容为空,无法获取关键信息生成摘要。

 

 

 

 

 

 

 

 

<think> 我们正在讨论SQL自连接的常见面试题。自连接是指同一个表与自己进行连接操作,通常用于处理具有层次结构的数据或需要比较同一表中不同行的情况。 根据引用[1]中提到的常见SQL面试题,我们可以总结几个自连接的典型应用场景: 1. 连续性问题:例如查找连续登录N天的用户、连续递增的数字等。 2. 层级关系问题:例如员工与经理的关系(同一个表中的员工和经理都是员工,经理ID指向同一表中的其他员工)。 3. 行与行之间的比较:例如比较同一产品不同月份的价格变化。 下面我们列举几个常见的自连接面试题: 题目1:员工表(employee)中包含员工ID(emp_id)和经理ID(mgr_id),其中经理ID也是员工ID。查询每个员工的姓名及其经理的姓名。 题目2:订单表(orders)有订单ID(order_id)、客户ID(customer_id)和订单日期(order_date)。找出每个客户连续两天都有下单的记录。 题目3:学生成绩表(scores)有学生ID(student_id)、科目(subject)和成绩(score)。找出每个科目中成绩高于该科目平均分的学生。 注意:题目3虽然也可以用窗口函数解决,但使用自连接(通过先计算每个科目的平均成绩,然后连接)也是一种方法。 接下来,我们给出这些题目的SQL解答(以MySQL为例): 题目1:员工表自连接 假设员工表为employee,字段为emp_id, emp_name, mgr_id(经理的emp_id) ```sql SELECT e.emp_name AS employee_name, m.emp_name AS manager_name FROM employee e LEFT JOIN employee m ON e.mgr_id = m.emp_id; ``` 题目2:订单表自连接(连续两天) 假设订单表orders有字段order_id, customer_id, order_date(日期格式) 思路:自连接同一客户的不同订单,且订单日期相差一天。 ```sql SELECT a.customer_id, a.order_date AS date1, b.order_date AS date2 FROM orders a JOIN orders b ON a.customer_id = b.customer_id WHERE DATEDIFF(b.order_date, a.order_date) = 1; ``` 题目3:学生成绩表自连接(高于科目平均分) 假设成绩表scores字段:student_id, subject, score 步骤:先计算每个科目的平均成绩,然后通过自连接将平均成绩连接到每个学生的成绩行,再比较。 ```sql SELECT s.student_id, s.subject, s.score FROM scores s JOIN ( SELECT subject, AVG(score) AS avg_score FROM scores GROUP BY subject ) t ON s.subject = t.subject WHERE s.score > t.avg_score; ``` 另外,自连接还可以用于删除重复记录、查找对称对等场景。 自连接面试题注意点: 1. 别名:同一个表连接必须使用别名来区分。 2. 连接条件:确定连接的条件,避免产生笛卡尔积。 3. 性能:自连接可能产生大量的中间结果,注意优化。 引用[2]中提到,在优化时要注意大表和小表的位置,以及使用合适的索引(如连接字段的索引)来提高性能[^2]。同时引用[3]提到联合索引在范围查询时的注意事项,在自连接中如果连接条件涉及范围(如日期差),也需要注意索引的使用[^3]。 最后,自连接是SQL中非常重要的操作,也是面试中经常考察的点。 §§相关问题§§ 1. SQL自连接与内连接、外连接有什么区别和联系? 2. 在自连接中如何避免重复记录? 3. 自连接和子查询在性能上有什么差异? </think> ### SQL自连接常见面试题解析 自连接是SQL中处理层级关系、连续事件和行间比较的重要技术,以下是常见面试题目及解决方案: #### 1. 员工层级关系查询 **场景**:员工表含员工ID、姓名和经理ID(指向同一表),查询员工及其经理信息 ```sql -- 创建表 CREATE TABLE employees ( emp_id INT PRIMARY KEY, emp_name VARCHAR(50), mgr_id INT REFERENCES employees(emp_id) ); -- 自连接查询 SELECT e.emp_name AS employee, m.emp_name AS manager FROM employees e LEFT JOIN employees m ON e.mgr_id = m.emp_id; ``` **输出示例**: | employee | manager | |----------|---------| | Alice | Bob | | Bob | null | | Charlie | Bob |[^1] --- #### 2. 连续日期检测 **场景**:登录记录表,找出连续登录≥3天的用户 ```sql -- 创建表 CREATE TABLE logins ( user_id INT, login_date DATE ); -- 自连接解决方案 SELECT DISTINCT a.user_id FROM logins a JOIN logins b ON a.user_id = b.user_id AND b.login_date = a.login_date + INTERVAL 1 DAY JOIN logins c ON a.user_id = c.user_id AND c.login_date = a.login_date + INTERVAL 2 DAY; ``` **优化点**:在`user_id`和`login_date`建联合索引提升性能[^3] --- #### 3. 价格波动分析 **场景**:商品价格表,找出价格连续上涨的商品 ```sql SELECT a.product_id, a.date AS start_date, c.date AS end_date FROM prices a JOIN prices b ON a.product_id = b.product_id AND b.date = a.date + INTERVAL 1 DAY AND b.price > a.price JOIN prices c ON a.product_id = c.product_id AND c.date = b.date + INTERVAL 1 DAY AND c.price > b.price; ``` --- #### 4. 部门工资比较 **场景**:员工表含部门ID和工资,查找工资高于本部门平均工资的员工 ```sql SELECT e1.emp_name, e1.salary, e1.dept_id FROM employees e1 WHERE e1.salary > ( SELECT AVG(e2.salary) FROM employees e2 WHERE e2.dept_id = e1.dept_id ); ``` **性能提示**:使用窗口函数`AVG() OVER(PARTITION BY dept_id)`更高效[^2] --- ### 自连接核心要点 1. **别名必需**:同一表多次使用必须定义不同别名 2. **索引优化**:连接字段需建立索引,避免全表扫描[^3] 3. **层级深度**:N层关系需要N-1次自连接 4. **去重处理**:使用`DISTINCT`避免重复记录 5. **空值处理**:外连接(`LEFT JOIN`)代替内连接避免数据丢失 > 自连接本质是将单表视为多表进行关联,重点考察对**数据关系建模**和**连接条件设计**的理解[^1][^2]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值