问题
在这个SQL问题中,我们给了三张表:学生,朋友和包裹。
学生表包含两个列:
- ID(学生的ID)和
- 名称(学生的名字)。
朋友表包含两个列:
- ID(学生的ID)和
- friend_id(学生唯一最好的朋友的ID)。
包装表包含两个列:
- ID(学生的ID)和
- 薪水(以每月$ $为$的薪水提供给学生的薪水)。
这是这三个表的视觉表示:
任务是编写一个SQL查询,该查询输出那些最好的朋友提供的薪水比他们更高的学生的名字。名称应按照提供给最好的朋友的薪水订购。还可以保证,没有两个学生获得相同的薪水。
解释
考虑以下输入:
预期的输出应为:
Samantha
Julia
Scarlet
这是原因:
萨曼莎(Samantha),朱莉娅(Julia)和斯嘉丽(Scarlet)最好的朋友都得到了比他们更高的薪水,而阿什利(Ashley)最好的朋友却没有。
解决方案
在这里,我提出了两种使用略有不同方法的SQL解决方案。每个人都有自己的优势,劣势和适用性。
直接加入方法
第一个源代码使用直接加入操作来链接所有表的必要数据:
SELECT s.name
FROM Students s JOIN Friends f ON s.ID = f.ID
JOIN Packages p1 ON p1.ID = s.ID
JOIN Packages p2 ON p2.ID = f.Friend_ID
WHERE p1.Salary < p2.Salary
ORDER BY p2.Salary
在这种方法中,我们直接根据各自的IDS加入学生,朋友和包装表。加入桌子后,我们滤除了(来自p1
)薪水的学生(来自p2
的薪水),最终由朋友的薪水订购结果。这是一种直接且易于理解的方法。
子查询加入方法
第二个解决方案在加入之前使用子查询来预滤伍:
SELECT s1.Name
FROM
(
SELECT s.ID, s.Name, p.Salary
FROM Students s
JOIN Packages p ON s.ID = p.ID
) s1
JOIN
(
SELECT f.ID, p.Salary [Friend_Salary]
FROM Friends f
JOIN Packages p ON f.Friend_ID = p.ID
) s2 ON s1.ID = s2.ID
WHERE s1.Salary < s2.Friend_Salary
ORDER BY s2.Friend_Salary
在这里,我们没有立即加入所有表,而是创建了两个子Queries s1
和s2
,以预先加入学生和包装桌,以及朋友和包装表。然后,我们加入ID上的这两个子查询结果,过滤学生的薪水小于朋友的薪水,并由朋友的薪水订购结果。如果表之间存在显着尺寸差异,则这种方法可以更有效,因为它会在联接操作之前降低数据的大小。
结论
两种方法都在解决此问题方面有效,其差异主要在于其性能和可伸缩性,而桌子尺寸不同。根据实际的数据分布和大小,由于加入过程中的数据大小降低,子查找方法可能会提供更好的性能。
您可以在HackerRank中找到原始问题。
有关更有见地的解决方案和与技术相关的内容,请随时在我的Beacons page上与我联系。