SQL智能连接

时间:2016-03-06 08:33:32

标签: sql sql-server join relational-database

;WITH tblEmployee AS (
SELECT * FROM (VALUES
(1, 'Tom', 'Male', 4000, 1),
(2, 'Pam', 'Female', 3000, 3),
(3, 'John', 'Male', 3500, 1),
(4, 'Sam', 'Male', 4500, 2),
(5, 'Todd', 'Male', 2800, 2),
(6, 'Ben', 'Male', 7000, 1),
(7, 'Sara', 'Female', 4800, 3),
(8, 'Valarie', 'Female', 5500, 1),
(9, 'James', 'Male', 6500, NULL),
(10, 'Russell', 'Male', 8800, NULL)) AS E(ID, Name, Gender, Salary, DepartmentId)
), 
tblDepartment AS (
SELECT * FROM (VALUES
(1, 'IT', 'London', 'Rick'),
(2, 'Payroll', 'Delhi', 'Ron'),
(3, 'HR', 'New York', 'Christie'),
(4, 'Other Department', 'Sydney', 'Cindrella')) AS D(Id, DepartmentName, Location, DepartmentHead)
)

左表是员工表和右表部门表。

我正在网上阅读教程,并对教师提供的解释感到困惑:

如果我在上面的两个表上运行此查询:

Select E.Name, E.Gender, E.Salary, D.DepartmentName
from tblEmployee as E
Left Join tblDepartment as D
On tblEmployee.departmentID = tblDepartment.Id
Where tblEmployee.departmentID IS Null;

我对上面SQL代码中的最后一行有点困惑。当你说:

Where tblEmployee.departmentID IS Null

上面的代码行是否在运行这些代码行之后形成的新表上执行:

Select E.Name, E.Gender, E.Salary, D.DepartmentName
from tblEmployee as E
Left Join tblDepartment as D
On tblEmployee.departmentID = tblDepartment.Id

所以基本上它会检查所形成的新表:只有将部门ID作为NULL的地方才会显示这些行。我只是想澄清这一行:Where tblEmployee.departmentID IS Null是在新表格形成正确后运行的?

3 个答案:

答案 0 :(得分:1)

“ SQL Intelligent Joins”是一个罕见的措词。实际上,唯一的可靠参考(以及此问题中的数据集)来自YouTube SQL教程:

Advanced or Intelligent Joins by Kudvenkat

简而言之,“智能联接”的语法更简洁,而在声明数据集的边界时则更为明确。以以下两个查询为例。它们具有相同的输出,但是语法不同:

-- intelligent join
select
    e.Name,
    e.Gender,
    e.Salary

from tblEmployee as e
    left join tblDepartment as d on e.departmentID = d.Id
        and d.DepartmentName = 'IT'

where
    d.DepartmentName is null

上面的查询使用“智能联接”。

-- where clause subquery
select
    e.Name,
    e.Gender,
    e.Salary

from tblEmployee as e

where
    e.departmentID not in (select id from tblDepartment where departmentName = 'IT')
    or e.departmentID is null

上面的此查询在where子句中使用子查询。

但是,即使两个输出是等效的,第一个查询也更简单,并提供了更多信息。它的本质是“如果不在IT部门,请给我所有雇员的性别和薪水”。相反,where子句子查询语法较长,并且混淆了表的联接方式。如果有的话,请尝试首先使用智能联接来实现所需的输出。

答案 1 :(得分:0)

这是一个左外连接。这会将public class MainActivity extends AppCompatActivity { private String layoutName; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.layoutName = getResources().getResourceEntryName(R.layout.activity_main); Log.d("TAG", layoutName); } } 中未加入tblEmployee的所有记录。

enter image description here

答案 2 :(得分:0)

OP的假设是正确的,以下是有关SQL JOIN 语法的一些方面,对于初学者一旦掌握了 join的概念将有所帮助是。通常,仅仅知道某件事是正确的或有效的还不够,我们需要了解其背后的原因。

  

This answer from @fqhv使用了我个人最喜欢的有关不同连接类型的信息图形之一。

首先,请注意查询this reference is a good general explanation的执行顺序,请注意,每个数据库引擎可以并且可能会做不同的事情,但这是一个普遍的期望。

Execution Order of SQL Statements

一个重要的要点是:

  

联接语句实际上是查询中FROM子句的一部分

请注意,在过滤后 发生后,如何评估select语句,这意味着直到那时我们都可以考虑使用FROM子句来表示一个非常宽的表其中包含FROM子句中表示的表的 ALL 中的 ALL 列。

您可以通过在select语句中使用字段通配符(*,星号)来演示此操作,而不用指定任何特定字段。 -在此示例中,我将注释掉SELECTWHERE子句,以演示调试或研究SQL结果的常用技术。 -注意:由于在FROM子句中使用了表别名,因此我已将查询更改为使用那些别名代替表名,该查询实际上将立即运行。 -我们希望所有列和所有行都将在以下查询中返回

-- Select E.Name, E.Gender, E.Salary, D.DepartmentName
SELECT *
from tblEmployee as E
Left Join tblDepartment as D
On E.departmentID = D.Id
-- Where E.departmentID IS Null;
ID          Name    Gender Salary      DepartmentId Id          DepartmentName   Location DepartmentHead
----------- ------- ------ ----------- ------------ ----------- ---------------- -------- --------------
1           Tom     Male   4000        1            1           IT               London   Rick
2           Pam     Female 3000        3            3           HR               New York Christie
3           John    Male   3500        1            1           IT               London   Rick
4           Sam     Male   4500        2            2           Payroll          Delhi    Ron
5           Todd    Male   2800        2            2           Payroll          Delhi    Ron
6           Ben     Male   7000        1            1           IT               London   Rick
7           Sara    Female 4800        3            3           HR               New York Christie
8           Valarie Female 5500        1            1           IT               London   Rick
9           James   Male   6500        NULL         NULL        NULL             NULL     NULL
10          Russell Male   8800        NULL         NULL        NULL             NULL     NULL

(10 rows affected)

希望,从查询中查看结果确实应该在您可以选择和过滤的字段上描绘出一幅图画。

您会注意到,使用LEFT JOIN导致某些行仅包含NULL表中字段的tblDepartment值。 LEFT OUTER JOIN

非常强大
    如果未指定OUTEROUTER,则
  • INNER是JOIN的默认修饰符。将其称为LEFT JOIN
  • 同样有效

对于当前JOIN语句的 LEFT 中的每个结果,至少返回1行,也就是将先前联接到FROM子句上的所有字段,即使我们刚刚加入的表中没有匹配的行。

有了这些信息,当我们想要列出不在任何部门中的所有学生的列表时,我们可以简单地使用插入空值的LEFT JOIN行为轻松地确定要删除的行。

Where E.departmentID IS Null添加到查询中时,将仅返回没有部门的行。

-- Select E.Name, E.Gender, E.Salary, D.DepartmentName
SELECT *
from tblEmployee as E
Left Join tblDepartment as D
On E.departmentID = D.Id
Where E.departmentID IS Null;
ID          Name    Gender Salary      DepartmentId Id          DepartmentName   Location DepartmentHead
----------- ------- ------ ----------- ------------ ----------- ---------------- -------- --------------
9           James   Male   6500        NULL         NULL        NULL             NULL     NULL
10          Russell Male   8800        NULL         NULL        NULL             NULL     NULL
  

值得说明的是,这是一个非常简单的示例,完全不需要使用JOIN即可获得相似的结果,但这是演示所有类型JOIN的良好数据集。

例如,即使先前JOINed字段中没有匹配的行,RIGHT JOIN也会为JOINed表中的每个结果返回至少一行。

SELECT *
from tblEmployee as E
RIGHT Join tblDepartment as D
On E.departmentID = D.Id
ID          Name    Gender Salary      DepartmentId Id          DepartmentName   Location DepartmentHead
----------- ------- ------ ----------- ------------ ----------- ---------------- -------- --------------
1           Tom     Male   4000        1            1           IT               London   Rick
3           John    Male   3500        1            1           IT               London   Rick
6           Ben     Male   7000        1            1           IT               London   Rick
8           Valarie Female 5500        1            1           IT               London   Rick
4           Sam     Male   4500        2            2           Payroll          Delhi    Ron
5           Todd    Male   2800        2            2           Payroll          Delhi    Ron
2           Pam     Female 3000        3            3           HR               New York Christie
7           Sara    Female 4800        3            3           HR               New York Christie
NULL        NULL    NULL   NULL        NULL         4           Other Department Sydney   Cindrella

使用这些信息,我们现在可以轻松地过滤结果以显示所有拥有 0 名员工的部门:

SELECT *
from tblEmployee as E
RIGHT Join tblDepartment as D
On E.departmentID = D.Id
Where E.ID IS Null;
ID          Name    Gender Salary      DepartmentId Id          DepartmentName   Location DepartmentHead
----------- ------- ------ ----------- ------------ ----------- ---------------- -------- --------------
NULL        NULL    NULL   NULL        NULL         4           Other Department Sydney   Cindrella

SQL智能联接

这确实是一些点击诱饵,这不是一个名词,您会发现很多书都同意,但是我们都支持它的想法:

  

一个好的SQL程序员或DBA应该开发一种如何翻译查询要求的技能,并智能地应用JOIN语句来简化要求。

使用JOIN的 intelligent 应用程序可以解决开发人员本能遍历集合的许多问题,但不是全部,而是很多。因此,当您第一次想到 iterate 时,需要花一些时间来探索数据查询中的不同JOIN语句。

您当然可以通过将专门针对JOINed表运行的过滤器条件移至以下位置,使实现JOIN语句和复杂WHERE子句的查询变得更智能,更易于阅读,从而使它们更易于阅读。 JOIN表达式本身,它不在OP原始问题的范围内,无法通过此数据集解决,但@alexusWong goes into this in his response

  • 不要误以为您只能加入 ON 一个字段比较,可以使用几乎所有标准WHERE语句作为{{1}的附加条件} statemet。