我不确定:这是反加入吗?

时间:2016-03-31 18:38:48

标签: mysql join left-join

我正在处理着名的SQLzoos的第一个问题,我正在处理using Null部分:http://sqlzoo.net/wiki/Using_Null

问题是:

  

列出部门为NULL的教师。

相应的SQL查询将是:

SELECT t.name
  FROM teacher t
WHERE t.dept IS NULL

这是一种反连接吗?具体来说,这是左反连接吗?

3 个答案:

答案 0 :(得分:1)

这根本不是连接。

该声明仅过滤了没有指定部门的教师的记录。

设置差异

教师和部门之间的差异,teacher \ department将是一种“反加入”

SELECT
t.name
FROM teacher t
LEFT JOIN department d ON d.id = t.dept_id
WHERE d.id IS NULL

乍一看,此语句执行您的语句所做的事情,如果强制执行外键引用,它将保证完全执行。但是,本声明的一个用途是检索被分配到已被删除的部门的教师(例如,如果英语升级部门和英语作为第二郎部门被重组为英语部门。)

对称差异

另一个“反连接”是对称差异,如果它们不能连接,则选择两个 ONLY 的元素,即

(teacher \ department) U (department \ teacher)

我无法想到使用教师和部门的激励示例,但是在支持FULL OUTER JOIN的数据库上编写对称差异的一种方法是:

SELECT
t.name
FROM teacher t
FULL OUTER JOIN department d ON d.id = t.dept_id
WHERE d.id IS NULL OR t.id IS NULL

对于MySQL,这个语句必须写成两个语句的并集。

SELECT
t.name teacher_name, d.name department_name
FROM teacher t
LEFT JOIN department d ON d.id = t.dept_id
WHERE d.id IS NULL

UNION ALL

SELECT
t.name teacher_name, d.name department_name
FROM teacher t
LEFT JOIN department d ON d.id = t.dept_id
WHERE t.id IS NULL

通过我的一个项目,我发现这是对称差异的用法:

背景:

  

我有三个表:usersusers_gameplay_summaryusers_transactions_summary。我需要通过电子邮件向过去7天内创建帐户的用户发送电子邮件 AND 以下其中一项   have transacted but have not playedplayed but have not transacted.

要获取列表,我有这个查询(注意,这是为Postgresql编写的,不适用于MySQL,但它说明了对称差异用例):

SELECT 
COALESCE(g.user_id, t.user_id) user_id
FROM users_gameplay_summary g
FULL OUTER JOIN users_transactions_summary t ON t.user_id = g.user_id

WHERE COALESCE(g.user_id, t.user_id) IN (
          SELECT user_id 
          FROM users 
          WHERE created_at > CURRENT_DATE - '7 day'::interval)
  AND (g.user_id IS NULL OR t.user_id IS NULL)

答案 1 :(得分:0)

不完全是,你现在没有加入任何东西, 如果是左反连接,您也可以访问部门名称。 (虽然它会是NULL)

您的sql代码将是您提出的问题的正确答案。

左反连接将是:

SELECT t.name
FROM teacher t
LEFT JOIN dept d ON d.id = t.dept
WHERE d.id IS NULL

答案 2 :(得分:0)

要解决在没有指定部门的情况下列出教师的问题,您不需要在JOINteacher表之间dept

dept表基本上是您加入的字典表,用于将ID转换为相应的名称。

teacher表格中有一个dept列,通常可以FOREIGN KEYiddept列。

您的查询不是ANTI-JOIN。这是一个使用一个表的简单projection and selection查询。

SELECT t.name
  FROM teacher t
WHERE t.dept IS NULL

对于ANTI-JOIN,您至少需要在多个表之间进行JOIN操作。

通常情况下ANTI-JOIN可能如下:

  

使用LEFT JOIN

SELECT *
FROM table1 t1
LEFT JOIN table2 t2
  ON t1.join_column = t2.join_column
WHERE t2.join_column IS NULL
  

使用NOT EXISTS

SELECT *
FROM table1 t1
WHERE NOT EXISTS ( 
  SELECT 1
  FROM table2 t2
  WHERE t1.join_column = t2.join_column
  )