SQL是数据分析和数据处理最重要的编程语言之一,所以与数据科学相关的工作(如数据分析师、数据科学家、数据工程师)在面试时总会问到SQL的问题。SQL面试问题旨在评估候选人的技术和解决问题的能力。所以对于考生来说,关键不仅是要根据样本数据编写正确的查询,还要像真实世界的数据集一样考虑各种场景和边缘情况。在这篇文章中,我将描述SQL面试问题中的常见模式,并提供一些在SQL查询中巧妙处理这些问题的技巧。1.问问题要在SQL面试中做好最重要的事情,就是尽可能多地提问,以获得有关给定任务和数据样本的所有详细信息。充分了解需求后,您可以节省大量迭代问题的时间并很好地处理边缘情况。我注意到许多候选人经常在没有完全理解SQL问题或数据集的情况下开始编写解决方案。然后,在我指出他们的解决方案存在问题后,他们不得不反复修改查询。最后,他们浪费了大量的面试时间在迭代上,甚至到最后可能都找不到合适的解决方案。我建议大家在参加SQL面试的时候,就好像是在和一个商业伙伴一起工作。所以在你提供解决方案之前,你应该了解数据请求的所有要求。例如找到薪水最高的前3名员工。示例Employee_salary表在这里,您应该要求面试官明确说明“前三名”的确切含义。我应该在结果中包括3名员工吗?你希望我如何处理这段关系?此外,仔细检查示例员工数据。Salary字段的数据类型是什么?计算前需要清空数据吗?2、选择哪种JOIN在SQL中,JOIN通常用于合并多个表的信息。有四种不同类型的JOIN,但在大多数情况下我们只使用INNER、LEFT和FULLJOIN,因为RIGHTJOIN不是很直观并且可以使用LEFTJOIN轻松重写。在SQL面试中,您需要根据给定问题的具体要求选择要使用的正确JOIN。例如,找出每个学生修读的课程总数。(提供学生ID、姓名和选修的课程数。)Student和Class_history表示例您可能已经注意到,并不是所有出现在Class_history表中的学生都出现在Student表中,这可能是因为这些学生已经毕业。(这实际上在事务数据库中非常典型,因为不再活动的记录往往会被删除。)根据面试官是否希望在结果中包含毕业生,我们需要使用LEFTJOIN或INNERJOIN将两个表合并:WITHclass_countAS(SELECTstudent_id,COUNT(*)ASnum_of_classFROMclass_historyGROUPBYstudent_id)SELECTc.student_id,s.student_name,c.num_of_classFROMclass_countc--CASE1:仅包含活跃学生JOINstudentsONc.student_id=s.student_id--CASE2:includeallstudents--LEFTJOINstudentsONc.student_id=s.student_id3.GROUPBYGROUPBY是SQL中最重要的函数,因为它广泛用于数据聚合。如果您在SQL问题中看到诸如sum、average、minimum或maximum之类的关键字,这很好地表明您应该在查询中使用GROUPBY。一个常见的陷阱是在GROUPBY过滤数据时混淆WHERE和HAVING-我见过很多人犯过这个错误。例如,计算每学年每个学生必修课的平均GPA,找出每个学期符合Dean’sList(GPA≥3.5)资格的学生。Gpa_history表示例由于我们在GPA计算中只考虑必修课,因此我们需要使用WHEREis_required=TRUE来排除选修课。我们需要每个学年每个学生的平均GPA,因此我们将GROUPBYstudent_id和School_year列并取Gpa列的平均值。最后,我们只保留学生平均GPA高于3.5的行,这可以使用HAVING来实现。组合如下:SELECTstudent_id,school_year,AVG(gpa)ASavg_gpaFROMgpa_historyWHEREis_required=TRUEGROUPBYstudent_id,school_yearHAVINGAVG(gpa)>=3.5注意:凡在查询中使用GROUPBY时,只能选择Group-按列和聚合列,因为其他列中的行级信息被丢弃。4.SQL查询执行顺序大多数人会从SELECT开始,从上到下编写SQL查询。但是你知道吗,SELECT是在SQL引擎执行函数之后才执行的?以下是SQL查询的执行顺序:FROM,JOINWHEREGROUPBYHAVINGSELECTDISTINCTORDERBYLIMIT,OFFSET再次考虑前面的例子:由于我们想在计算平均GPA之前过滤掉选修课,所以我使用WHEREis_required=TRUE而不是HAVING,因为WHERE在执行前会在GROUPBY和HAVING中。我不能写HAVINGavg_gpa>=3.5的原因是Avg_gpa被定义为SELECT的一部分,因此不能在SELECT之前执行的步骤中引用它。我建议在编写查询时遵循引擎的执行顺序,这在编写复杂查询时很有用。5.Windowfunction窗口函数也经常出现在SQL面试中。有五个常见的窗口函数:**RANK/DENSE_RANK/ROW_NUMBER:**它们通过对特定列进行排序来为每一行分配一个等级。如果给出任何分区列,则该行将在其所属的分区组中排名。**LAG/LEAD:**它根据指定的顺序和分区组从上一行或下一行中检索列值。在SQL面试中,了解排名函数之间的区别以及知道何时使用LAG/LEAD非常重要。示例查找每个部门中收入最高的前3名员工。又如Employee_salary表当一个SQL问题要求计算“TOPN”时,我们可以使用ORDERBY或rank函数来回答这个问题。但是在这个例子中,它要求计算“每个Y中的TOPNX”,这强烈暗示我们应该使用排名函数,因为我们需要对每个分区组中的行进行排名。下面的查询准确地找到了3个最高薪的员工,不管他们之间的关系如何,如下所示:3--注意:当使用ROW_NUMBER时,每一行都有一个唯一的排名编号,并且随机分配绑定记录的排名。例如,Rimsha和Tiah在不同的查询运行中可能排名2或3。此外,根据这样做的关系方式,我们可以选择其他排名函数。再次重申,细节很重要!ROW_NUMBER、RANK、DENSE_RANK结果比较6.重复SQL面试中另一个常见的陷阱是忽略数据重复。尽管样本数据中的某些列似乎具有不同的值,但面试官希望候选人像处理真实数据集一样考虑所有可能性。例如,在前面的示例Employee_salary表中,可以让员工共享相同的名称。避免由重复引起的潜在问题的一种简单方法是始终使用ID列来唯一标识不同的记录。示例使用Employee_salary表查找每个部门所有员工的总工资。正确的解决办法是GROUPBYemployee_id,然后用SUM(employee_salary)计算总工资。如果需要员工姓名,则在末尾加入Employee表,获取员工姓名信息。错误的方法是使用GROUPBYemployee_name。7.NULL在SQL中,任何谓词都可以产生True、False和NULL三个值之一,这是Unknown或Missing数据值的保留关键字。在处理NULL数据集时,它可能会出乎意料地棘手。在SQL面试中,面试官可能会特别注意解决方案是否处理NULL值。有时,很明显一个列不能为Nullabl,但对于大多数其他列来说,很可能会出现NULL值。建议:验证样本数据中的关键列是否可为空,如果是,则利用IS(NOT)NULL、IFNULL和COALESCE等函数来涵盖这些边缘情况。8、沟通最后一点也很重要:在SQL面试的时候随时和面试官沟通。我面试过的许多应聘者都很沉默寡言,只有在有疑问时才会说出来。当然,如果他们最终找到了完美的解决方案,那也很好。但是,在技术面试期间保持对话的进行通常很有价值。例如:你可以谈谈你对问题和数据的理解,解释你打算如何解决这个问题,为什么你使用某些功能而不是其他选项,以及正在考虑哪些极端情况。9.总结从提出问题和收集你需要的细节开始在INNER、LEFT和FULLJOIN之间仔细选择使用GROUPBY聚合数据并正确使用WHERE和HAVING了解三个排名函数之间的差异了解何时使用LAG/LEAD窗口functions如果你在创建复杂的查询时遇到困难,尽量按照SQL执行顺序考虑重复和NULL值等潜在的数据问题与面试官交流你的想法
