麒麟v10 上部署 TiDB v5.1.2 生产环境优化实践
611
2023-05-17
如何拿下SQL面试?这些技巧和陷阱应该要知道……
SQL是数据分析和处理最基本的编程语言之一,因此,无论是面试数据分析师、数据科学家、数据工程师,还是其他相关工作,都免不了要过这一关。
实战技术和解决问题的能力是SQL面试中考察的重点,应聘者不仅要基于示例数据编写正确的查询,还要考虑各种场景和边缘情况,就如同在处理实际数据集。
笔者曾经帮助求职者设计过SQL面试问题,并模拟了面试,也多次亲身参加了大型科技公司和初创企业SQL求职面试的实战。本文将对SQL面试问题的常见模式进行阐释,分享在SQL查询中灵活处理这些模式的技巧。
快掏出小本本开始学习吧~
提问
要拿下一场SQL面试,最重要的在于尽可能多地提问,以确保自己掌握了给定任务和数据样本的所有细节。理解这些需求有助于节省迭代问题的时间,也有助于更好地处理边缘情况。
许多应聘者会在没有深入理解SQL问题或数据集之前,直接开始解决问题。在笔者指出解决方案中的问题之后,他们不得不反复修改查询,在迭代上浪费了大量时间,甚至到最后都没找到正确的解决方案。
笔者的建议是将SQL面试视为在与业务合作伙伴一起工作,保持这种心态,面试者就会在提供解决方案之前努力收集数据请求的所有需求。
示例
从下表中找出薪资最高的三位职员。
样本:职员薪资表
面试者应该让面试官仔细阐述“前三名”的概念——结果中必须只有三名职员吗?对于并列的处理有何要求?此外,面试者应仔细查看示例职员的数据——薪资字段的数据类型是什么?需要在计算之前清除数据吗?
何种连接
在SQL中,连接经常用于组合来自多个表的信息。共有四种不同类型的连接,但是在大多数情况下,我们只使用自然连接、左连接和全连接,因为右连接并不直观,而且使用左连接很容易重写。在SQL面试中,面试者需要根据给定问题的特定要求,选择正确的连接。
示例
找出每位学生上课的总节数。(已知学生证、姓名和上课次数。)
样本:学生名单和课程数据表
可以注意到,并非所有出现在课程数据表中的学生都存在于学生名单中,这可能是因为这些学生已经毕业(这在事务数据库中非常典型,数据不活跃时就会被删除)。在了解清楚面试官是否希望将不活跃的学生包括在内之后,可以根据情况使用左连接和自然连接两种方式来合并表格。
WITHclass_count AS ( SELECT student_id, COUNT(*) ASnum_of_class FROM class_history GROUP BY student_id ) SELECT c.student_id, s.student_name, c.num_of_class FROM class_count c -- CASE 1: include only active students JOIN student s ON c.student_id = s.student_id-- CASE 2: include all students -- LEFT JOIN student s ON c.student_id = s.student_id
GROUP BY
GROUP BY是SQL中最基本的函数,广泛用于数据聚合。如果在一个SQL问题中出现了sum、average、minimum或maximum等关键字,则极有可能应该在查询中使用GROUP BY。一个常见的陷阱是,在用GROUP BY过滤数据时将WHERE和HAVING混淆——许多人都犯过这个错误。
示例
计算每个学生每学年的必修课平均绩点,并找出每学期中绩点≥3.5的学生。
样本:GPA数据表
在计算GPA时只考虑必修课,因此需要使用 WHERE is_required = TRUE来排除选修课。需要计算每个学生每学年的平均绩点,因此需要用GROUP BY命令按student_id 和school_year 两列来进行分组,并取gpa的平均值。最后,只保留平均GPA高于3.5的行,这可以通过HAVING实现。再将以上所得进行结合:
SELECT student_id, school_year, AVG(gpa) AS avg_gpa FROM gpa_history WHERE is_required = TRUE GROUP BY student_id, school_year HAVING AVG(gpa) >= 3.5
记住,无论何时在查询中使用GROUP BY,都只能选择要分组的列,然后进行聚合,因为其他列中的行级信息已被丢弃。
可能有人想知道WHERE和HAVING之间有什么区别,或者想知道为什么不直接用avg_gpa>= 3.5,而是指定函数。下一节将会给出详细解释。
SQL查询语句执行顺序
在写SQL查询时,大多数人是按照自上而下的顺序,但他们可能并不知道SELECT是SQL引擎最后执行的函数之一。以下是SQL查询的执行顺序:
FROM, JOINWHEREGROUP BYHAVINGSELECTDISTINCTORDER BYLIMIT, OFFSET
回头再看前面的示例。因为需要在计算平均绩点之前过滤掉选修课,所以可以用 WHERE is_required = TRUE来代替HAVING,因为WHERE在GROUP BY和HAVING之前执行。不用HAVINGavg_gpa >= 3.5的原因是avg_gpa被定义为SELECT的一部分,所以不能在SELECT之前执行的步骤中引用。
图源:unsplash
笔者建议在编写查询时按照执行顺序编写,这在编写复杂查询时非常有用。
窗口函数
窗口函数也经常出现在SQL面试中。五种常见的窗口函数如下:
RANK /DENSE_RANK /ROW_NUMBER:通过对特定列排序,为每行分配一个秩。如果给定了任何分区列,则行将在其所属的分区组中排列。LAG /LEAD:根据指定的顺序和分区组从前一行或后一行检索列值。
在SQL面试中,面试者必须知道排名函数之间的差异,以及何时使用LAG/LEAD。
示例
找出每个部门中薪资最高的3名职员。
样本:职员薪资表2
当SQL问题要求找出“前N名”时,可以使用ORDER BY或ranking函数来回答。但以上示例要求计算“每个Y中的前N 个X”,这代表着面试者应该使用排ranking函数,因为需要对每个分区组中的行进行排列。
下面的查询能准确找到3名薪资最高的职员,不考虑并列:
WITH TAS ( SELECT *, ROW_NUMBER() OVER (PARTITION BYdepartment_id ORDER BY employee_salary DESC) AS rank_in_dep FROM employee_salary) SELECT * FROM T WHERE rank_in_dep <= 3-- Note: When using ROW_NUMBER, each row will have aunique rank number and ranks for tied records are assigned randomly. Forexmaple, Rimsha and Tiah may be rank 2 or 3 in different query runs.
另外,根据面试官对并列情况处理的要求,面试者也可选择不同的ranking函数。再次提醒大家,细节很重要!
ROW_NUMBER、RANK和 DENSE_RANK 三种函数的对比。
重复项
SQL面试中的另一个常见陷阱是忽略重复项。尽管有些列在示例数据中似乎具有不同的值,但面试者还是应该考虑所有可能的情况,就像在处理真实的数据集一样。例如,在上例的员工薪资表中,不同职员可能出现同名情况。
想要避免重复项引起的潜在问题,一个简单的方法是始终使用ID列来标识不同的记录,避免重复。
示例
根据职员薪资表,找出所有部门每个职员的总工资。
正确的解决方案是按employee_id 来分组,使用SUM(employee_salary)来计算总薪资。如果需要员工姓名,可在末尾加入职员表格来检索职员的姓名信息。
用employee_name来分组是错误的。
NULL
在SQL中,任何谓词都可能产生以下三个值之一:true、false和NULL。NULL这一关键词用于指代未知或空缺数据。处理NULL可能会非常棘手。在SQL面试中,面试官会特别注意面试者在解决过程中是否处理了NULL。在一些情况下,很明显某列数据不能为空值(例如ID列),但大多数其他的列很可能会出现NULL。
笔者建议面试者确认示例数据中的关键列是否可以为空值,如果可以,则可以使用IS (NOT) NULL、IFNULL和COALESCE 等函数来覆盖这些边缘情况。
沟通
另外很重要的一点在于——在面试过程中保证流畅的沟通。
在笔者面试过的求职者中的很多人,除非真的有问题,否则几乎不说话。如果他们能在最后给出完美的解决方案,那倒也没什么大问题,但在技术面试中保持与面试者的沟通通常会有所助益。例如,面试者可以谈论自己对问题和数据的理解、自己是如何计划解决问题的、使用这个函数而不是另外一个的原因、或者正在考虑的边缘情况。
总结
先提问,收集所需的详细信息。谨慎选择连接方式——自然连接,左连接还是全连接。使用GROUP BY聚合数据,合理使用WHERE和HAVING。了解三个ranking函数之间的差异。了解何时使用LAG/LEAD窗口功能。如果需要创建的查询太过复杂,尝试按照SQL执行顺序编写。考虑潜在的数据问题,如重复项和空值。与面试官沟通思维过程。
面试顺利冲鸭!
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。