今天我尝试了一些更复杂的MySQL查询,我注意到MySQL的LEFT JOIN不能与WHERE子句一起使用.我的意思是,它确实会返回一些记录,但它不会返回右侧为空的记录.
例如,假设我们需要表格:
albums ; albums_rap id artist title tracks ; id artist title rank ---- -------- ---------- --------------- ; ---- --------- ----- -------------- 1 John Doe Mix CD 20 ; 3 Mark CD #7 15 2 Mark CD #7 35 ;
当我运行此查询时:
SELECT
t1.artist as artist,
t1.title as title,
t1.tracks as tracks,
t2.rank as rank,
FROM
albums as t1
LEFT JOIN
albums_rap as t2
ON
t1.artist LIKE t2.artist
AND
t1.title LIKE t2.title
WHERE
t2.rank != 17
Run Code Online (Sandbox Code Playgroud)
我明白了:
artist title …
我一直在移植oracle选择,我一直在运行很多查询,如下所示:
SELECT e.last_name,
d.department_name
FROM employees e,
departments d
WHERE e.department_id(+) = d.department_id;
Run Code Online (Sandbox Code Playgroud)
...和:
SELECT last_name,
d.department_id
FROM employees e,
departments d
WHERE e.department_id = d.department_id(+);
Run Code Online (Sandbox Code Playgroud)
有没有转换(+)语法的所有变体的指南/教程?什么是语法甚至调用(所以我可以搜索谷歌)?
更好 ..有没有一个工具/脚本可以为我做这个转换(首选免费)?某种优化器?我有大约500个这样的查询到端口..
该标准何时逐步淘汰?任何信息表示赞赏.
我试图更直观地掌握 SQL 连接。就在昨天,我了解了如何将 RIGHT JOIN 重写为 LEFT JOIN(通过翻转表格的顺序),这帮助我更好地理解了这两个连接的工作方式。
但是,现在我想知道是否可以将 INNER JOIN 重写为带有 WHERE 条件的 LEFT JOIN——这意味着它们的逻辑可能是等效的(“逻辑”不是指执行计划,而是将描述预期的结果集)。
喜欢:
SELECT * FROM HeaderTable
INNER JOIN DetailTable
ON HeaderTable.ID = DetailTable.ParentID
Run Code Online (Sandbox Code Playgroud)
我将其读作“向我显示HeaderTable和DetailTable表中在HeaderTable.ID和DetailTable.ParentID字段中具有匹配值的所有记录。” 与以下相同:
SELECT * FROM HeaderTable
LEFT JOIN DetailTable
ON HeaderTable.ID = DetailTable.ParentID
WHERE HeaderTable.ID = DetailTable.ParentID
Run Code Online (Sandbox Code Playgroud)
这也是我读作“让我看看表中的所有记录HeaderTable和DetailTable其中的价值HeaderTable.ID相同的值DetailTable.ParentID。”
这些会返回相同的结果集吗?我更多地询问逻辑是否相同,而不是一个比另一个更有效。
如果我可能会问,请不要用任何维恩图来回答,因为这些似乎并没有准确地描述连接的逻辑。
想象一下,我有两个简单的表,例如:
CREATE TABLE departments(dept INT PRIMARY KEY, name);
CREATE TABLE employees(id PRIMARY KEY, fname, gname,
dept INT REFERENCES departments(dept));
Run Code Online (Sandbox Code Playgroud)
(当然简化).
我可以有以下任何陈述:
SELECT * FROM employees e INNER JOIN departments d ON e.dept=d.dept;
SELECT * FROM employees e NATURAL JOIN departments d;
SELECT * FROM employees e JOIN departments d USING(dept);
Run Code Online (Sandbox Code Playgroud)
可以在这里找到一个工作示例:SQL Fiddle:http://sqlfiddle.com/#!15/864a5/13/10
它们都给出了几乎相同的结果 - 当然是相同的行.
我一直更喜欢第一种形式,因为它具有灵活性,可读性和可预测性 - 你清楚地定义了什么与什么有关.
现在,除了第一种形式有重复的列之外,其他两种形式是否真的有优势?或者他们只是语法糖?
我可以看到后一种形式的缺点是你应该命名你的主键和外键相同,这并不总是实用的.
我在课堂上学习加入,但我并没有完全掌握一些概念.有人可以解释具有多个连接的语句是如何工作的吗?
SELECT B.TITLE, O.ORDER#, C.STATE FROM BOOKS B
LEFT OUTER JOIN ORDERITEMS OI ON B.ISBN = OI.ISBN
LEFT OUTER JOIN ORDERS O ON O.ORDER# = OI.ORDER#
LEFT OUTER JOIN CUSTOMERS C ON C.CUSTOMER# = O.CUSTOMER#;
Run Code Online (Sandbox Code Playgroud)
我相信我理解BOOKS表是连接BOOKS和ORDERITEMS的第一个外连接中的左表.即使书中没有ORDERITEM,也会显示所有BOOKS.第一次加入后,我不确定到底发生了什么.
当ORDERS加入时,左表是哪个表,哪个是右表?对于客户来说也一样.这是我迷路的地方.
有什么不同?
SELECT a.name, b.name
FROM a, b;
SELECT a.name, b.name
FROM a
CROSS JOIN b;
Run Code Online (Sandbox Code Playgroud)
如果没有区别那为什么两者都存在呢?
我的脑日很慢......
我加入的表格:
Policy_Office:
PolicyNumber OfficeCode
1 A
2 B
3 C
4 D
5 A
Run Code Online (Sandbox Code Playgroud)
Office_Info:
OfficeCode AgentCode OfficeName
A 123 Acme
A 456 Acme
A 789 Acme
B 111 Ace
B 222 Ace
B 333 Ace
... ... ....
Run Code Online (Sandbox Code Playgroud)
我想执行搜索以返回与办公室名称相关联的所有策略.例如,如果我搜索"Acme",我应该得到两个策略:1和5.
我当前的查询如下所示:
SELECT
*
FROM
Policy_Office P
INNER JOIN Office_Info O ON P.OfficeCode = O.OfficeCode
WHERE
O.OfficeName = 'Acme'
Run Code Online (Sandbox Code Playgroud)
但是这个查询返回多行,我知道这是因为第二个表有多个匹配.
如何编写查询只返回两行?
我的SQL Server数据库中有3个表.
它们链接在一起,如图所示(线条连接到图片中的右侧行)

我有一个查询,它应该返回所有补偿tblreparations信息,其中包含有关修复内容的一些信息,但它会返回3次修复,一次为客户端(荷兰语中的klant)分配给它的每台笔记本电脑,而补偿表(荷兰语的修理)laptopID每行只包含一个
这是查询:
SELECT AankopenReparaties.Id,
AankopenReparaties.KlantenId,
AankopenReparaties.actietype,
AankopenReparaties.voorwerptype,
laptopscomputers.merk,
laptopscomputers.model,
laptopscomputers.info,
AankopenReparaties.info,
AankopenReparaties.Prijs,
AankopenReparaties.lopend
FROM AankopenReparaties, laptopscomputers
WHERE (aankopenreparaties.lopend = 'lopend');
Run Code Online (Sandbox Code Playgroud)
它返回这个

它应该只有一行,因为赔偿表(aankopenreparaties)只包含一行一个 laptopID
有谁知道如何解决这一问题?
请帮助,因为它应尽快修复(这是学校的任务)
我试图过滤我的结果,只显示一个住在特定城市酒店的人的名字。到目前为止我所拥有的是
select guestName
from Guest
join Hotels on hotelNo=1
Run Code Online (Sandbox Code Playgroud)
但是,当我这样做时,结果页面会列出数据库中的每个来宾名称,而不是留在hotelNo1 中的名称。
所以我看了几张图来理解连接之间的区别,我遇到了这个图像:
也许问题在于用Venn Diagrams来代表这个问题.但是看看第一次加入,左上角,基本上只是A?B在那里有什么不同?
编辑:https://blog.jooq.org/2016/07/05/say-no-to-venn-diagrams-when-explaining-joins/
这个网站解释得很好
sql ×9
join ×5
database ×3
left-join ×3
sql-server ×3
inner-join ×2
cross-join ×1
mysql ×1
oracle ×1
outer-join ×1
php ×1
plsql ×1
where ×1
where-clause ×1