当谈及求职面试中最常出现的SQL面试问题时,我不是在说给你具体的问题。这将是一项不可能完成的任务,因为有成千上万的问题。
幸运的是,这些问题所测试的SQL概念并不多。这并不意味着你应该只解决我即将展示的面试问题,或者只知道选定的题目。
但是,如果你专注于最常见的题目,你就有可能涵盖面试中测试的大部分概念。当然,问题可以有不同的难度,这将需要更多或更少关于特定主题的知识。不过,这些概念往往是相同的。
虽然这些题目可以被看作是华丽的(尤其是如果你是一个SQL书呆子!),但我更愿意把它们称为 "不可避免的七种"。
- 聚合、分组和排序
- 筛选
- JOIN和集合运算符
- 子查询和 CTEs
- CASE语句
- 窗口功能
- 文本和日期操作
这些主题通常在编码SQL问题中测试,但它们也可能出现在非编码类型的问题中。
编码SQL面试问题
编码问题正如其名称所示:它们测试你使用SQL概念编写代码的能力。
1.聚合、分组和排序
理论
SQL聚合函数是对多条记录进行计算并返回一个值的函数。最常用的聚合函数是。
| 聚合函数 | 说明 |
| COUNT() | 计算行的数量。 |
| SUM() | 返回行数的总和。 |
| AVG() | 计算各行的平均数值。 |
| MIN() | 返回最低值。 |
| MAX() | 返回最高值。 |
当单独使用时,这些函数将只返回一个值。诚然,这并不是很复杂。
当与GROUP BY和ORDER BY子句一起使用时,聚合函数对数据科学家来说变得更有价值。
GROUP BY用于根据行的值将一个或多个列的数据分组。每一个不同的值(或按多列分组的值的组合)将形成一个单独的数据组。这样一来,就有可能显示被聚合的数据的额外信息。
ORDER BY的作用是对查询的输出进行排序。数据可以按升序或降序进行排序。此外,你还可以按一个或多个列进行排序。
使用这两个子句的聚合函数成为创建报告、计算指标和整理数据的踏脚石。它们允许你对数据进行数学运算,并以清晰和可展示的方式显示你的发现。
SQL问题
SQL面试问题#1:寻找更新记录
"我们有一个包含员工和他们工资的表,然而,一些记录是旧的,包含过时的工资信息。假设工资每年都在增长,请找到每个员工的当前工资。输出他们的ID,名字,姓氏,部门ID,和目前的工资。按雇员ID升序排列你的列表。"
问题链接:https://platform.stratascratch.com/coding/10299-finding-updated-records?code_type=1
数据
这个问题给你一个表:MS_employee_salary
| id | int |
| 姓氏 | varchar |
| 姓氏 | varchar |
| 薪资 | varchar |
| department_id | int |
下面是该表的数据样本。
解决方法
如果工资每年都在增加,那么最新的工资也是最高的工资。要获取它,请使用MAX()聚合函数。按雇员和部门对数据进行分组。你还应该显示按雇员ID升序排序的输出,为此使用ORDER BY子句。
SELECT id,
first_name,
last_name,
department_id,
max(salary)
FROM ms_employee_salary
GROUP BY id,
first_name,
last_name,
department_id
ORDER BY id ASC;
输出
SQL面试题#2:按第一次参加奥运会的年份对所有国家排序
"找出每小时的平均旅行距离。
输出小时和相应的平均行驶距离。
按小时升序对记录进行排序"。
要找到平均距离,使用AVG()函数,然后按列小时对输出进行分组和排序。
如果你写出正确的解决方案,你会得到这样的结果。
SQL面试题#3:按第一次参加奥运会的年份对所有国家排序
"按照所有国家第一次参加奥运会的年份来排序。
输出国家奥林匹克委员会(NOC)的名称和所需的年份。
按年份和NOC的升序对记录进行排序"。
该代码需要按列noc对数据进行分组,并使用MIN()聚合函数来查找第一年的参赛情况。为了对输出进行充分排序,使用ORDER BY。
如果你得到这个结果,那么你就做对了一切。
2.筛选
理论
如果数据过滤被定义为选择数据的一个子集,那么数据过滤的方式有很多。即使是人们通常不认为是这样的,例如,SELECT语句和JOIN。但它们就是这样,它们只选择部分数据。
当考虑过滤数据时,通常会想到两个关键词(或者当你使用PostgreSQL时,会想到三个。
- WHERE
- (HAVING)
- (LIMIT)
WHERE子句的目的是在数据汇总之前对其进行过滤。其语法反映了这一点,它必须写在GROUP BY子句之前。
当使用WHERE子句过滤数据时,有许多运算符可以使用。
| 操作符 | 说明 |
| = | 等于 |
| < | 小于 |
| > | 大于 |
| <= | 小于或等于 |
| >= | 大于或等于 |
| <> | 不等于 |
| BETWEEN | 在指定的范围内 |
| 喜欢 | 寻找一个模式 |
| 输入 | 等于括号中列出的值 |
HAVING子句与WHERE子句的作用相同,只是它在聚合后过滤数据。当然,它只能在SQL查询中的GROUP BY子句之后使用。
WHERE子句中的所有运算符在HAVING子句中也可以使用。
这两个子句都允许通过使用AND/OR逻辑运算符对一个或多个条件进行过滤。
使用这两个子句可以为你的计算增加另一个维度。基本的使用使得只显示你感兴趣的数据而不是大部分数据成为可能。这意味着你不仅可以选择你想要的列,还可以根据其值选择你想要的行。与聚合函数一起使用,你就可以通过过滤聚合函数的输入,以及如果你愿意,过滤它们的输出,对更详细的数据子集进行计算。这增加了你所掌握的计算的复杂性。
LIMIT子句简单地指定了你希望看到的输出的行数。子句中的整数值等于作为结果显示的行数。当你想对数据进行排序时,这一点特别有用,例如,显示前N名的销售额、雇员、工资等。
SQL问题
SQL面试题#4:找出Uber通过名人获得超过2000个客户的那一年
"找出那一年Uber通过利用名人做广告获得了超过2000个客户。"
数据
表uber_advertising有四列。
| 年份 | int |
| 广告_渠道 | varchar |
| 花费的钱 | int |
| 获得的客户 | int |
这里是表的预览。
解决方案的方法
该解决方案是一个简单的SELECT语句,只有一列。然而,你不需要所有的年份。问题要求你只输出那些广告渠道是通过名人的,并且有超过2000个客户获得的。要做到这一点,把这两个条件放到WHERE子句中。
SELECT year
FROM uber_advertising
WHERE advertising_channel = 'celebrities' AND
customers_acquired > 2000;
输出
运行代码,它将只输出一个符合条件的年份。2018.
SQL面试题#5:查找最低和最高检查分数不同的所有企业
"查找所有最低和最高检查分数不同的企业。
输出相应的企业名称和每个企业的最低分和最高分。
根据企业名称将结果按升序排列。"
问题的链接:platform.stratascratch.com/coding/9731…
为了回答这个问题,使用MIN()和MAX()函数来找到最高和最低的检查分数,并按业务分组数据。然后使用HAVING子句,只显示最高和最低分数不相等的企业。最后,按照企业名称的字母顺序对输出进行排序。
你的输出应该是这个。
SQL面试问题#6:找到加班费最高的前3个职位
"找到加班费率最高的前3个工作。
输出所选记录的职位名称。
根据加班费按降序对记录进行排序。"
这个问题要求你同时使用WHERE和LIMIT子句。使用WHERE找到加班费不为NULL且不为0的职位名称,将数据从最高到最低的加班费排序。然后,简单地将输出限制在前三行,你就得到了:加班费率最高的前三份工作。
如输出结果所示,只有三个这样的工作。
3.JOIN和集合运算符
理论
到目前为止,你已经被谴责只使用一个表。不幸的是,没有一个可敬的数据库是由一个表组成的。为了充分利用可用的数据,你需要知道如何将两个或多个表的数据结合起来。
JOIN是你正在寻找的SQL功能:它使在共同列上连接表成为可能。
在SQL中有五种不同的JOIN类型。
| JOIN类型 | 说明 |
| (INNER) JOIN | 只返回两个表中的匹配记录。 |
| 左(外)连接 | 从左表返回所有的数据,只从右表返回匹配的行。 |
| 右(外)连接 | 返回来自右表的所有数据,并且只返回来自左表的匹配行。 |
| 完全外连接 | 返回来自两个表的所有记录。 |
| 交叉连接 | 将一个表中的所有行与第二个表中的所有行结合起来。 |
当我提到匹配的行时,我是指在两个表中相同的行或值。
前四种连接方式是最常用的,但CROSS JOIN有时也可以使用。
还有一种连接表的方式是自连接。它不是一种独特的连接类型:任何JOIN类型都可以用于自连接,这只是意味着你把表和它自己连接起来。
集合运算符用于合并两个或多个查询的输出。
| 集合运算符 | 描述 |
| 合并 | 合并由查询产生的唯一行。 |
| UNION ALL | 合并所有的查询结果的记录,包括重复的记录。 |
| INTERSECT | 只返回在两个查询的输出中出现的记录。 |
| 例外(EXCEPT | 从一个查询中返回唯一的记录,并且只返回那些在第二个查询的输出中出现的记录。 |
SQL问题
SQL面试问题#7:昂贵的项目
"给定一个项目的列表和映射到每个项目的员工,通过分配给每个员工的项目预算金额进行计算。输出应该包括项目名称和每个员工的项目预算,四舍五入到最接近的整数。将你的列表按每个雇员的最高预算的项目先排序。"
问题链接:https://platform.stratascratch.com/coding/10301-expensive-projects?code_type=1
数据
该问题给了你两个表。
表:MS_projects
| id | int |
| 标题 | varchar |
| 预算 | int |
这里是表的预览。
表:ms_emp_projects
| emp_id | int |
| project_id | int |
下面是一个数据例子。
解决方法
首先要做的是按员工计算项目预算。这看起来比实际情况要复杂:只需将列预算除以雇员人数,这是用COUNT()函数得到的。然后,将结果转换为浮动数据类型,以获得小数位。这个计算是在用于四舍五入的ROUND()函数内完成的。在这种情况下,除法的结果被转换为数字数据类型,并进行四舍五入,没有小数位。
SELECT语句使用了两个表中的列。这是可能的,因为在FROM子句中使用了INNER JOIN来连接这些表。它们是在列id等于列project_id的情况下连接的。
最后,结果按项目和预算分组,而输出则按比例降序排序。
SELECT title AS project,
ROUND((budget/COUNT(emp_id)::float)::numeric, 0) budget_emp_ratio
FROM ms_projects a
INNER JOIN ms_emp_projects b ON a.id = b.project_id
GROUP BY title,
budget
ORDER BY budget_emp_ratio DESC;
输出
代码的输出应该是这样的,部分显示在下面。
SQL面试问题#8:查找西班牙人在各个国家的登录次数
"查找按国家划分的西班牙语使用者的登录次数。
输出国家以及相应的登录次数。
按登录次数降序排列记录。"
在解决方案中,使用COUNT()函数来计算登录次数。由于所需的数据是在两个表中找到的,因此有必要连接它们。为此,请使用INNER JOIN。在列user_id和事件为'login',而用户的语言为'spanish'的情况下,将两个表连接起来。按地点对数据进行分组,并从最高到最低的登录次数进行排序。
正确的代码将返回三个国家,其登录次数如下。
SQL面试问题#9:数字之和
"找出索引小于5的数字的总和,以及索引大于5的数字的总和。在单独的一行中输出每个结果"。
该问题的链接:https://platform.stratascratch.com/coding/10008-sum-of-numbers?code_type=1
你要写的代码包括两个SELECT语句。一个将找到索引小于5的数字的总和,另一个将对索引大于5的数字做同样的事情。
你所要做的就是在这两条语句之间加上UNION ALL来获得输出。
4.子查询和CTEs
理论
子查询和CTEs为你的代码增加了灵活性。它们都用于有几个步骤的更复杂的计算,其结果用于主计算。
有一些特定的关键字,你可以在其中使用子查询。
- SELECT
- FROM
- WHERE
- HAVING
- INSERT
- 更新
- DELETE
它们最常用于在WHERE或HAVING子句中过滤数据,但当查询结果作为一个表时,也可以作为FROM子句中的表使用。一般来说,它们允许在一个查询中进行复杂的计算。
至于CTE或通用表表达式,它们也有同样的目的。不同的是,它们更接近人类的计算步骤逻辑,所以它们的代码更整洁。通常情况下,CTE需要编写更少的代码,而且比用子查询编写的相同计算更易读。
CTE有两个主要部分:一个CTE和一个引用CTE的查询。
一般的CTE语法是。
WITH cte_name AS (
SELECT…cte_definition..
)
SELECT …
FROM cte_name;
使用 WITH 关键字调用 CTE。在给出CTE后,一个名称是AS,然后在括号内是CTE定义。这个定义是一个SELECT语句,为CTE提供指令。
主查询也是一个SELECT语句,但这个语句引用了CTE。
它们的名字里有个词叫表,这是有原因的:CTE是一个临时结果,只有在运行CTE的时候才能访问,所以它类似于一个临时表。这就是为什么你可以像其他表一样在FROM子句中使用它。
SQL问题
SQL面试题#10:按职位和性别划分的收入
"根据员工的头衔和性别,找到平均总报酬。总报酬的计算方法是把每个员工的工资和奖金都加起来。但是,并不是每个员工都能得到奖金,所以在计算时,不考虑没有奖金的员工。一个员工可以获得不止一个奖金。
输出员工的头衔、性别(即性别),以及平均总报酬。"
问题链接:https://platform.stratascratch.com/coding/10077-income-by-title-and-gender?code_type=1
数据
问题中使用的第一个表是sf_employee。
表:sf_employee
| id | int |
| 姓氏 | varchar |
| 姓氏 | varchar |
| 年龄 | int |
| 性别 | varchar |
| 雇员头衔 | varchar |
| 部门 | varchar |
| 薪资 | int |
| 目标 | int |
| 电子邮件 | varchar |
| 城市 | varchar |
| 地址 | varchar |
| manager_id | int |
表中的数据看起来像这样。
表:sf_bonus
| workers_ref_id | int |
| 奖金 | int |
| 奖金日期 | datetime |
这里是数据。
解决方法
这段代码中的主SELECT语句使用表sf_employee和子查询数据。子查询使用SUM()函数计算员工的总奖金;这就是为什么它也按工人的ID分组数据。子查询像其他表一样与表sf_employee连接。在这种情况下,它使用的是INNER JOIN。
然后,主查询将使用子查询的数据来计算平均总报酬,包括工资和收到的总奖金。
最后,结果将按雇员和性别分组。
SELECT e.employee_title,
e.sex,
AVG(e.salary + b.ttl_bonus) AS avg_compensation
FROM sf_employee e
INNER JOIN
(SELECT worker_ref_id,
SUM(bonus) AS ttl_bonus
FROM sf_bonus
GROUP BY worker_ref_id) b ON e.id = b.worker_ref_id
GROUP BY employee_title,
Sex;
输出
该解决方案将返回四条记录作为结果。
SQL面试问题#11:有真实床位和互联网的最便宜的街区
"寻找那些你可以睡在有互联网的别墅里的真正的床上,同时支付最低价格的社区。"
为了解决这个问题,在WHERE子句中使用子查询来获得满足某些条件的价格。将使用MIN()函数来寻找带互联网的别墅中的真床的最低价格。使用等号表示两个条件,并在条件两边用通配符(%)表示ILIKE。
然后在主查询中使用相同的条件(真床、别墅、互联网)。
有一个小区满足了这些条件。
SQL面试题#12:广告渠道有效性
"找出2017年至2018年期间每个广告渠道的平均效力(均包括在内)。效益的计算方法是花费的总资金与获得的总客户的比率。
输出广告渠道以及相应的平均效力。按平均效力升序对记录进行排序。"
问题链接:https://platform.stratascratch.com/coding/10012-advertising-channel-effectiveness?code_type=1
每个CTE都以关键词WITH开始,之后是CTE的名称。然后是AS,在括号里,你定义了CTE的主体,即SELECT语句,你将在外层查询中调用它。
在这个例子中,你应该使用CTE来总结花费的钱和获得的客户。你通过在WHERE子句中设置这个条件,为2017年和2018年做这一切。
在外部查询中,选择广告渠道,然后将花费的总金额除以获得的客户总数,这将给你带来平均效果。
将输出结果按效果升序排序。
5.CASE语句
理论
这是一个条件语句,是一个SQL版本的IF-THEN-ELSE逻辑。它指示代码通过一组条件,根据数据是否满足条件,定义应该返回哪个结果。
CASE语句的语法是。
CASE
WHEN condition
THEN result
ELSE result
END AS case_stetement_alias;
它还允许设置多个条件,而不是只有一个。
case语句最常用于给数据贴标签或与聚合函数一起使用,这时要根据特定的标准进行计算。
SQL问题
SQL面试问题#13:预订与非预订
"显示一个用户进行搜索导致成功预订的平均次数,以及一个用户进行搜索但没有导致预订的平均次数。输出应该有一个名为action的列,其值为'不预订'和'预订',以及名为average_searches的第二列,其值为每个action的平均搜索次数。如果预订日期为空,则考虑预订没有发生。要注意的是,只有当他们的入住日期匹配时,搜索才会与预订相连"。
问题链接:https://platform.stratascratch.com/coding/10124-bookings-vs-non-bookings?code_type=1
数据
你必须使用问题提供的两个表。
表:airbnb_contacts
| id_guest | varchar |
| id_host | varchar |
| id_listing | varchar |
| ts_contact_at | datetime |
| ts_reply_at | datetime |
| ts_accepted_at | 日期 |
| 帐户 | 日期 |
| ds_checkin | 日期时间 |
| ds_checkout | 日期 |
| n_guests | 寸 |
| n_messages | int |
下面是数据预览。
表:airbnb_searches
| ds | datetime |
| id_user | varchar |
| ds_checkin | 日期时间 |
| ds_checkout | 日期时间 |
| n_searches | 误差 |
| n_nights | 浮动 |
| n_guests_min | int |
| n_guests_max | int |
| Origin_country | varchar |
| 最小过滤价格 | 浮动 |
| 最高过滤价格 | 浮动 |
| 筛选器_房间类型 | varchar |
| 邻居 | datetime |
该表的前几行显示如下。
解决方案的方法
该解决方案在SELECT语句中使用CASE语句来标记数据。当列ts_booking_at中没有NULL值时,它将得到标签 "books"。如果它是NULL,它将变成 "不预订"。这个CASE语句将在新的列动作中显示其结果。
另外,在SELECT语句中还有一个AVG()函数,用于查找平均搜索次数。
使用LEFT JOIN从两个表中获取数据。最后,输出是按数据标签分组的。
SELECT CASE
WHEN c.ts_booking_at IS NOT NULL THEN 'books'
ELSE 'does not book'
END AS action,
AVG(n_searches) AS average_searches
FROM airbnb_searches s
LEFT JOIN airbnb_contacts c ON s.id_user = c.id_guest
AND s.ds_checkin = c.ds_checkin
GROUP BY 1;
输出结果
上述查询返回所需的输出。
SQL面试题#14:Lyft司机的流失率
"找出所有年份Lyft司机的全球流失率。以比率的形式输出。"
问题链接:https://platform.stratascratch.com/coding/10016-churn-rate-of-lyft-drivers?code_type=1
这个问题要求你在聚合函数中使用CASE语句;准确地说,是COUNT()。用它来计算离开的司机,也就是那些结束日期不是空的司机。用结果除以司机总数,并将其转换为小数。
如果你做得很好,你应该得到流失率。
SQL面试问题#15:找出收到奖金和没有收到奖金的员工人数
"找出收到奖金和没有收到奖金的员工的数量。
输出是否收到奖金的指示,以及相应的员工人数。
例如:如果收到了奖金。1,如果没有:0。"
在这个解决方案中,有一个子查询。该子查询使用CASE语句来确定哪些员工收到了奖金,哪些没有。这是根据奖金的日期和值是否为空来完成的。要做到这一点,你需要使用LEFT JOIN连接问题中的两个表。
主查询将使用这个结果来计算有奖金和没有奖金的员工人数。
6.窗口函数
理论
SQL的窗口函数与聚合函数类似。不同的是,窗口函数以一种可以同时显示单个行和聚合值的方式来聚合数据。
一般来说,有三种不同类型的窗口函数。
- 聚合窗口函数
- 排名窗口函数
- 值窗口函数
| 聚合窗口函数 | 说明 |
| COUNT() | 计算行的数量。 |
| SUM() | 对数值进行求和。 |
| AVG() | 返回平均值。 |
| MIN() | 返回最小值。 |
| MAX() | 返回最大值。 |
| 排名窗口函数 | 说明 |
| ROW_NUMBER() | 按顺序排列行,不跳过行号,对具有相同数值的行给予相同的排名。 |
| RANK() | 用于排序,对相同的数值给予相同的排序,跳过下一个排序。 |
| DENSE_RANK() | 用于排序,对相同的值给予相同的排名,下一个排名不被跳过。 |
| PERCENT_RANK() | 以百分比值对数值进行排序。 |
| NTILE() | 将行分成若干个大小相同的组。 |
| 值窗口函数 | 说明 |
| LAG() | 允许从定义的前面的行数中访问数据。 |
| LEAD() | 允许从定义的后面的行数中获取数据。 |
| FIRST_VALUE() | 返回数据中的第一个值。 |
| LAST_VALUE() | 返回数据中的最后一个值。 |
| NTH_VALUE() | 返回定义的(第n)行的值。 |
窗口函数被这样称呼是有原因的。它们对与当前行相关的行进行计算。当前行和所有相关的行被称为一个窗口框架。
有五个子句对于使用窗口函数非常重要。
- 覆盖
- 分区(PARTITION BY
- ORDER BY
- 行
- 范围
OVER子句是强制性的,其目的是调用窗口函数。没有它,就没有窗口函数。
PARTITION BY子句是用来划分数据的。通过指定其中的列,你在指示窗口函数应该在哪个数据子集上进行计算。当省略PARTITION BY时,窗口函数将整个表作为一个数据集。
ORDER BY子句也是一个可选的子句。它指定了每个数据集中的逻辑顺序。换句话说,它不是用来对输出进行排序,而是用来设置窗口函数的工作方向。数据可以按升序或降序排列。
在分区中,你可以额外限制将被纳入窗口函数计算中的行。这被称为定义一个窗口框架。
ROWS子句定义了当前行之前和之后的固定数量的行。
RANGE也是如此,只不过不是基于行的数量,而是基于它们与当前行相比的值。
窗口函数增加了SQL的分析可能性。通过使用它们,你可以并排显示聚合和非聚合的数据,在多个层次上进行聚合,对数据进行排序,以及进行其他一些只用聚合函数无法实现的操作。
SQL问题
SQL面试问题#16:平均工资
"将每个员工的工资与相应部门的平均工资进行比较。
输出员工的部门、名字和工资,以及该部门的平均工资。"
问题链接:platform.stratascratch.com/coding/9917…
数据
有一个名为employee的表。
| id | int |
| 姓氏 | varchar |
| 姓氏 | varchar |
| 年龄 | int |
| 性别 | varchar |
| 雇员头衔 | varchar |
| 部门 | varchar |
| 薪资 | int |
| 目标 | int |
| 奖金 | 奖金 |
| 电子邮件 | varchar |
| 城市 | varchar |
| 地址 | varchar |
| manager_id | int |
这里是雇员的数据。
解决方法
查询选择部门、雇员的名字和他们的工资。第四列将计算出工资的AVG()。因为它是一个窗口函数,所以必须使用OVER()子句来调用它。通过使用部门作为数据分区,查询将返回各部门的平均工资,而不是整体工资。
SELECT department,
first_name,
salary,
AVG(salary) OVER (PARTITION BY department)
FROM employee;
输出结果
这些只是完整输出中的前五行。
SQL面试问题#17:对最活跃的客人进行排名
"根据客人与主机交换的信息数量进行排名。与其他客人有相同消息数量的客人应该有相同的排名。如果前面的排名是相同的,不要跳过排名。
输出排名、客人ID和他们所发送的总消息数。先按最高的总消息数排序"。
问题链接:https://platform.stratascratch.com/coding/10159-ranking-most-active-guests?code_type=1
这里你需要使用排名窗口函数,即DENSE_RANK()函数。不会有数据,分区,但使用ORDER BY,将消息的总和从高到低排序。此外,选择客人的ID,并计算窗口函数外的消息之和。
通过客人ID对数据进行分组,并从最高到最低的消息数对数据进行排序。
你的输出应该看起来像这样。
SQL面试问题#18:能量消耗总和
"按日期计算Meta/Facebook所有三大洲的数据中心的运行总能耗(即累积总能耗)。输出日期、运行中的总能耗和运行中的总百分比,四舍五入到最近的整数"。
问题链接:https://platform.stratascratch.com/coding/10084-cum-sum-energy-consumption?code_type=1
这是一道很难的问题,涵盖了我谈到的大部分话题。首先,你需要写一个CTE。用它来写三个SELECT语句,从每个表中选择所有的数据,并使用UNION ALL连接输出。
第二个CTE将使用第一个CTE的数据,使用SUM()聚合函数,按日期获取总能耗。
外部查询以如下方式使用来自第二个CTE的数据。SUM()窗口函数通过将数据从最早的日期排序到最新的日期来计算累积总和。
然后用这个窗口函数除以总能耗--你可以通过按日期计算能耗的总和得到--再乘以100,得到百分比。使用ROUND()函数将结果显示为四舍五入的整数,也就是说,不会有小数位。
这就是能让你从面试官那里得到分数的输出。
7.文本和日期操作
理论
数据科学家经常要处理数据库中的文本和日期/时间,而不仅仅是数值。这通常意味着从几个字符串中创建一个字符串,或只使用日期的一部分(如日、月、年)或一个字符串。
最常见的文本操作函数是。
| 文本功能 | 说明 |
| ||或 CONCAT() | 将多个字符串值串联成一个。 |
| CHAR_LENGTH() | 返回一个字符串中的字符数。 |
| LOWER() | 将字符串转换为所有小写字母。 |
| UPPER() | 将字符串转换为所有大写字母。 |
| SUBSTRING() | 返回字符串的一部分。 |
| TRIM() | 删除字符串开头和结尾的空格或任何其他字符。 |
| LTRIM() | 从字符串的开头删除空格或其他任何字符。 |
| RTRIM() | 从字符串的结尾处删除空格或其他任何字符。 |
| LEFT() | 返回从字符串开始的定义的字符数。 |
| RIGHT() | 返回从字符串末尾开始的定义的字符数。 |
两个最经常使用的日期/时间函数是。
| 日期/时间函数 | 说明 |
| EXTRACT() | 返回日期或时间的部分;SQL标准。 |
| DATE_PART() | 返回日期或时间的一部分;PostgreSQL专用。 |
文本和日期/时间函数在数据科学家清理数据时非常有用。当然,他们也可以使用日期/时间函数进行计算,如加减时间段,并将其用于数据过滤、聚合等。
SQL问题
SQL面试问题#19。待处理的索赔案
"计算一下2021年12月提交的索赔有多少仍在等待。当一项索赔既没有接受日期也没有拒绝日期时,它就是待定的。"
问题的链接:platform.stratascratch.com/coding/2083…
数据
该问题给了你cvs_claims表。
| claim_id | int |
| 帐号 | varchar |
| 提交的日期 | datetime |
| 接受的日期 | 日期 |
| 被拒绝的日期 | 日期时间 |
让自己熟悉这些数据。
解决方法
COUNT()函数是用来获取索赔数量的。你需要只计算符合特定条件的索赔。在EXTRACT()函数的帮助下,设置了两个标准。第一个是用于从索赔提交日期中提取月份。另一个EXTRACT()函数将从同一列中获取年份。这样,你就可以得到2021年12月提交的索赔。
WHERE子句中的下两个条件将只显示尚未接受或拒绝的索赔,也就是说,它们是待定的。
SELECT COUNT(*) AS n_claims
FROM cvs_claims
WHERE EXTRACT(MONTH
FROM date_submitted) = 12
AND EXTRACT(YEAR
FROM date_submitted) = 2021
AND date_accepted IS NULL
AND date_rejected IS NULL;
输出
这个解决方案显示有5个在2021年12月提交的未决索赔。
SQL面试问题#20。繁忙时段的电话
"Redfin帮助客户寻找经纪人。每个客户都会有一个独特的request_id,每个request_id都有几个调用。对于每个request_id来说,第一次调用是 "初始调用",而接下来的所有调用都是 "更新调用"。 有多少客户在下午3点到6点之间打过3次或更多的电话(初始电话和更新电话加起来)?"
问题的链接:https://platform.stratascratch.com/coding/2023-rush-hour-calls?code_type=1
该解决方案使用DATE_PART()函数而不是EXTRACT()。它在FROM子句中的子查询中这样做。子查询显示了客户,但不是所有的客户。首先,使用WHERE子句和D,ATE_PART()对数据进行过滤并转换为时间戳,这样子查询将只返回在15到17小时之间打电话的客户。
在使用HAVING子句进行分组后,还要对数据进行过滤。该条件只显示在上述时间段内有三个或更多通话的客户。
这个结果将在主查询中只用于计算客户的数量。
只有一个客户在15:00到17:00之间打了三次或以上的电话。
SQL面试问题#21:确定等级的规则
"找出用于确定每个等级的规则。在一个单独的列中显示规则,格式为'Score > X AND Score <= Y => Grade = A',其中X和Y是一个等级的下限和上限。将相应的等级及其最高和最低分数与规则一起输出。根据成绩以升序排列结果"。
问题链接:https://platform.stratascratch.com/coding/9700-rules-to-determine-grades?code_type=1
SELECT语句返回每个年级的最低和最高分数。最后一列用于用concatenate函数对规则进行标注。同时使用MIN()和MAX()函数,得到以下规则。
- A级:分数>89且<=100
- B级:分数>79且<=88
- C级:分数>69且<=79
当然,标签必须按照要求进行格式化。
输出是按等级分组和排序的。
以下是相关规则。
SQL理论面试问题
这些问题也是测试SQL知识,和编码问题一样。不同的是它们不需要写代码,但你必须解释SQL概念或它们之间的区别。
下面是这类问题的一些例子,都是测试我在编码问题部分提到的主题。
SQL面试问题#22:WHERE和HAVING
"SQL中的WHERE子句和HAVING子句的主要区别是什么?"
问题链接:https://platform.stratascratch.com/technical/2374-where-and-having
WHERE和HAVING都是用来过滤数据的。主要区别在于,WHERE子句是在聚合和GROUP BY之前用于过滤数据。HAVING子句过滤已经聚合的数据,写在GROUP BY子句之后。
SQL面试问题#23:左连接和右连接
"SQL中的左连接和右连接有什么区别?"
该问题的链接:https://platform.stratascratch.com/technical/2242-left-join-and-right-join
你可以先解释一下这两个外连接的相似性。然后你可以谈一谈它们的区别。提示:线索就在 "左 "和 "右 "中。
SQL面试问题#24:公共表表达式
"在SQL中,什么是公共表表达式?请举例说明你会在什么情况下使用它"。
该问题的链接:https://platform.stratascratch.com/technical/2354-common-table-expression
你已经看到了CTEs是如何工作的。你可以讲讲它们与子查询的比较,然后给出一个使用CTE的例子。编码问题就这样了。
总结
SQL面试问题通常有两种形式:编码和非编码。这两种问题类型最常测试的是 "不可避免的七项"。如果没有七个关键的SQL概念,你甚至不能想去参加面试。
专注于它们,才能覆盖面试时可能出现的最多的SQL问题。问题难度也是一个变量,所以解决简单和困难的问题所需的知识可能有很大的区别。
**内特-罗西迪是**一名数据科学家和在产品战略。他也是教授分析学的兼职教授,同时也是StrataScratch的创始人,这个平台通过顶级公司的真实面试问题帮助数据科学家准备面试。在Twitter上与他联系。StrataScratch或LinkedIn。