我正在处理着名的SQLzoos的第一个问题,我正在处理using Null
部分:http://sqlzoo.net/wiki/Using_Null
问题是:
列出部门为NULL的教师。
相应的SQL查询将是:
SELECT t.name
FROM teacher t
WHERE t.dept IS NULL
这是一种反连接吗?具体来说,这是左反连接吗?
答案 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
通过我的一个项目,我发现这是对称差异的用法:
背景:
我有三个表:
users
,users_gameplay_summary
,users_transactions_summary
。我需要通过电子邮件向过去7天内创建帐户的用户发送电子邮件 AND 以下其中一项have transacted but have not played
或played 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)
要解决在没有指定部门的情况下列出教师的问题,您不需要在JOIN
和teacher
表之间dept
。
dept
表基本上是您加入的字典表,用于将ID转换为相应的名称。
teacher
表格中有一个dept
列,通常可以FOREIGN KEY
列id
列dept
列。
您的查询不是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
)