为什么这两个 SQL 查询不做同样的事情?
Why don't these two SQL queries do the same thing?
以下来自黑客排名SQL(基本)认证来自本页,https://www.hackerrank.com/skills-verification
块 1
SELECT ei.employee_ID, ei.name
FROM employee_information AS ei, Last_quarter_bonus AS lqb
WHERE ei.division = 'HR'
AND lqb.bonus >= 5000;
区块 2
SELECT ei.employee_ID, ei.name
FROM employee_information AS ei, Last_quarter_bonus AS lqb
WHERE ei.division = 'HR'
AND lqb.bonus >= 5000
AND ei.employee_ID = lqb.employee_id;
这两个查询之间的唯一区别是最后一行,BLOCK 2 的第 5 行:
AND ei.employee_ID = lqb.employee_id;
但我不知道为什么需要那一行。
在我看来,第一段代码应该可以正常编译。
我不明白第5行的必要性是什么。
在我看来,第 3 行和第 4 行已经使第 5 行为真,而无需编写第 5 行。
那么,为什么我必须编写第 5 行才能让查询按照我想要的方式进行编译?
为什么这两个查询吐出不同的结果?
这是使用显式 JOIN 的 BLOCK 2 查询。这是评论中提到的首选语法。
SELECT ei.employee_ID, ei.name
FROM employee_information AS ei JOIN Last_quarter_bonus AS lqb
ON ei.employee_ID = lqb.employee_ID
WHERE ei.division = 'HR' AND lqb.bonus >= 5000;
这里的条件是在ON子句中指定的。需要此条件才能仅包含雇员与 employee_information
和 last_quarter_bounus
.
相同的行
AND ei.employee_ID = lqb.employee_id;
But i dont know why that line is necessary.
这一行表示连接条件。
查询涉及 2 tables,如您在 FROM 子句中所见。 table 名称之间的逗号将导致 CROSS JOIN(在这种情况下可能不那么明显,因为只有一个逗号)。
第二个查询使用 INNER JOIN,这也不明显,因为 FROM 子句看起来与第一个查询相同(table 名称,逗号 -> 交叉连接)。但是,条件 ei.employee_ID = lqb.employee_id 强制执行内部联接,这将减少结果集中的行数。
为了SQL代码更清晰,很多人推荐内连接使用JOIN ... ON ...语法,交叉连接使用CROSS JOIN语法
等效项:
-- use this
select *
from ei cross join lqb ;
-- avoid
select *
from ei, lqb ;
对于内连接...
-- use this
select *
from ei join lqb on ei.id = lqb.id ;
-- avoid
select *
from ei, lqb
where ei.id = lqb.id ;
您可以看到,在内部连接的情况下,如果您只使用 table 的列表(即 table 名称和逗号),WHERE 子句将因连接条件而变得混乱在 FROM 子句中(您加入的 table 越多,这种效果就越差)。
DBfiddle here.
第五行必须的。在这个问题中,它要求您查看两个 table 并编写一个语句来过滤输出以显示 HR 中的任何员工并获得 5000 或更多的奖金。
抛开语法偏好,
当您在第二块中执行此操作时,与第一块中的两个相比,您需要寻找三个条件。你有:
- 寻找在hr工作的员工的条件(ei.division = 'HR')
- 寻找奖金达到或超过 5000 的员工的条件 (lqb.bonus >= 5000)
和
- 将两个 table 联系在一起的条件 (ei.employee_ID = lqb.employee_id)。
因为 SQL 很笨,所以你必须准确地告诉它你想让它做什么。如果不关联两个 table 就无法关联两个搜索。
如果您将所有这些信息集中在一个 table 中,您将能够使用块 1 中的两个条件(无需连接)并获得您正在寻找的结果但是因为有两个table,所以你必须把它包括进去。
现在关于语法,当您声明一个联接时,您通常指定哪个列在两个 table 之间共享。因此,如果您要使用连接编写此语句,则最后一个条件将被烘焙到连接命令中,而不是位于底部(SELECT * FROM database1 AS db1 JOIN database2 AS db2 ON db1.commonColumn= db2.commonColumn)。这将使它看起来像这样:
SELECT ei.employee_ID, ei.name // columns to display
FROM employee_information AS ei // first table to look at
JOIN Last_quarter_bonus AS lqb // second table to look at
ON ei.employee_ID = lqb.employee_id // shared column between both tables
WHERE ei.division = 'HR' // condition 1
AND lqb.bonus >= 5000; // condition 2
当然代码的结构应该更加精简,但我在语句中为每个动作换行,这样我可以更好地解释每个组件的作用。
以下来自黑客排名SQL(基本)认证来自本页,https://www.hackerrank.com/skills-verification
块 1
SELECT ei.employee_ID, ei.name
FROM employee_information AS ei, Last_quarter_bonus AS lqb
WHERE ei.division = 'HR'
AND lqb.bonus >= 5000;
区块 2
SELECT ei.employee_ID, ei.name
FROM employee_information AS ei, Last_quarter_bonus AS lqb
WHERE ei.division = 'HR'
AND lqb.bonus >= 5000
AND ei.employee_ID = lqb.employee_id;
这两个查询之间的唯一区别是最后一行,BLOCK 2 的第 5 行:
AND ei.employee_ID = lqb.employee_id;
但我不知道为什么需要那一行。 在我看来,第一段代码应该可以正常编译。 我不明白第5行的必要性是什么。 在我看来,第 3 行和第 4 行已经使第 5 行为真,而无需编写第 5 行。
那么,为什么我必须编写第 5 行才能让查询按照我想要的方式进行编译?
为什么这两个查询吐出不同的结果?
这是使用显式 JOIN 的 BLOCK 2 查询。这是评论中提到的首选语法。
SELECT ei.employee_ID, ei.name
FROM employee_information AS ei JOIN Last_quarter_bonus AS lqb
ON ei.employee_ID = lqb.employee_ID
WHERE ei.division = 'HR' AND lqb.bonus >= 5000;
这里的条件是在ON子句中指定的。需要此条件才能仅包含雇员与 employee_information
和 last_quarter_bounus
.
AND ei.employee_ID = lqb.employee_id;
But i dont know why that line is necessary.
这一行表示连接条件。 查询涉及 2 tables,如您在 FROM 子句中所见。 table 名称之间的逗号将导致 CROSS JOIN(在这种情况下可能不那么明显,因为只有一个逗号)。
第二个查询使用 INNER JOIN,这也不明显,因为 FROM 子句看起来与第一个查询相同(table 名称,逗号 -> 交叉连接)。但是,条件 ei.employee_ID = lqb.employee_id 强制执行内部联接,这将减少结果集中的行数。
为了SQL代码更清晰,很多人推荐内连接使用JOIN ... ON ...语法,交叉连接使用CROSS JOIN语法
等效项:
-- use this
select *
from ei cross join lqb ;
-- avoid
select *
from ei, lqb ;
对于内连接...
-- use this
select *
from ei join lqb on ei.id = lqb.id ;
-- avoid
select *
from ei, lqb
where ei.id = lqb.id ;
您可以看到,在内部连接的情况下,如果您只使用 table 的列表(即 table 名称和逗号),WHERE 子句将因连接条件而变得混乱在 FROM 子句中(您加入的 table 越多,这种效果就越差)。
DBfiddle here.
第五行必须的。在这个问题中,它要求您查看两个 table 并编写一个语句来过滤输出以显示 HR 中的任何员工并获得 5000 或更多的奖金。
抛开语法偏好,
当您在第二块中执行此操作时,与第一块中的两个相比,您需要寻找三个条件。你有:
- 寻找在hr工作的员工的条件(ei.division = 'HR')
- 寻找奖金达到或超过 5000 的员工的条件 (lqb.bonus >= 5000) 和
- 将两个 table 联系在一起的条件 (ei.employee_ID = lqb.employee_id)。
因为 SQL 很笨,所以你必须准确地告诉它你想让它做什么。如果不关联两个 table 就无法关联两个搜索。
如果您将所有这些信息集中在一个 table 中,您将能够使用块 1 中的两个条件(无需连接)并获得您正在寻找的结果但是因为有两个table,所以你必须把它包括进去。
现在关于语法,当您声明一个联接时,您通常指定哪个列在两个 table 之间共享。因此,如果您要使用连接编写此语句,则最后一个条件将被烘焙到连接命令中,而不是位于底部(SELECT * FROM database1 AS db1 JOIN database2 AS db2 ON db1.commonColumn= db2.commonColumn)。这将使它看起来像这样:
SELECT ei.employee_ID, ei.name // columns to display
FROM employee_information AS ei // first table to look at
JOIN Last_quarter_bonus AS lqb // second table to look at
ON ei.employee_ID = lqb.employee_id // shared column between both tables
WHERE ei.division = 'HR' // condition 1
AND lqb.bonus >= 5000; // condition 2
当然代码的结构应该更加精简,但我在语句中为每个动作换行,这样我可以更好地解释每个组件的作用。