自联接与 WHERE 相结合的内部工作原理

Inner workings of a self join combined with a WHERE

我有一个table

contacts
---------
contact_id  company         contact
1000000001  Village Toys    John Smith
1000000002  Kids Place      Michelle Green
1000000003  Fun4All         Jim Jones
1000000004  Fun4All         Denise L. Stephens
1000000005  The Toy Store   Kim Howard

我想查找 Jim Jones 所在公司的所有联系人。 这是正确的设置。

1000000003  Fun4All         Jim Jones
1000000004  Fun4All         Denise L. Stephens

我使用了一个子查询来解决这个问题并且它有效我得到了正确的结果。 然后我尝试在 'Jim Jones' 上使用 where 进行自我内部连接,但得到的结果我无法理解。

SELECT tableA.contact_id, tableA.company, tableA.contact
FROM company AS tableA
JOIN company AS tableB
ON tableA.company = tableB.company
WHERE tableB.contact = 'Jim Jones'

我得到了正确的结果集

1000000003  Fun4All         Jim Jones
1000000004  Fun4All         Denise L. Stephens

但是如果我将 WHERE 更改为

WHERE tableA.contact = 'Jim Jones'

我明白了

1000000003  Fun4All         Jim Jones
1000000003  Fun4All         Jim Jones

为什么要这样做?这究竟是如何工作的? 我整晚都在想办法弄明白。 但这让我望而却步。我在 Google 上找到的例子无法让我理解。

数据库(在我的问题中,我更改了列名以进行澄清)

http://forta.com/books/0672336073/TeachYourselfSQL_SQLite.zip
http://forta.com/books/0672336073/TeachYourselfSQL_Oracle.zip
http://forta.com/books/0672336073/TeachYourselfSQL_MySQL.zip
http://forta.com/books/0672336073/TeachYourselfSQL_MicrosoftSQLServer.zip
http://forta.com/books/0672336073/TeachYourselfSQL_Access2007.zip
http://forta.com/books/0672336073/TeachYourselfSQL_OpenOfficeBase.zip

您可以使用这种方式来获得想要的结果。

SELECT *
FROM   TableName
WHERE  company IN (SELECT company
                   FROM   TableName
                   WHERE  contact = 'Jim Jones')  

在您的查询中,如果您将 WHERE tableB.contact = 'Jim Jones' 更改为 WHERE tableA.contact = 'Jim Jones',那么您也必须更改 SELECT 语句。

SELECT tableA.contact_id, tableA.company, tableA.contact
FROM company AS tableA
JOIN company AS tableB
ON tableA.company = tableB.company
WHERE tableB.contact = 'Jim Jones'

SELECT tableB.contact_id, tableB.company, tableB.contact
FROM company AS tableA
JOIN company AS tableB
ON tableA.company = tableB.company
WHERE tableA.contact = 'Jim Jones'

您必须这样做,因为您要从该结果中过滤。
(您正在使用 company 列进行自联接。)

SELECT *
FROM company AS tableA
JOIN company AS tableB
ON tableA.company = tableB.company

+-----------------+----------------+---------------------+----------------+----------------+---------------------+
| contact_id (A)  |  company (A)   |     contact (A)     | contact_id (B) |  company (B)   |     contact (B)     |
+-----------------+----------------+---------------------+----------------+----------------+---------------------+
|      1000000001 | Village Toys   | John Smith          |     1000000001 | Village Toys   | John Smith          |
|      1000000002 | Kids Place     | Michelle Green      |     1000000002 | Kids Place     | Michelle Green      |
|      1000000003 | Fun4All        | Jim Jones           |     1000000003 | Fun4All        | Jim Jones           |
|      1000000004 | Fun4All        | Denise L. Stephens  |     1000000003 | Fun4All        | Jim Jones           |
|      1000000003 | Fun4All        | Jim Jones           |     1000000004 | Fun4All        | Denise L. Stephens  |
|      1000000004 | Fun4All        | Denise L. Stephens  |     1000000004 | Fun4All        | Denise L. Stephens  |
|      1000000005 | The Toy Store  | Kim Howard          |     1000000005 | The Toy Store  | Kim Howard          |
+-----------------+----------------+---------------------+----------------+----------------+---------------------+

要获得解释,请执行以下操作:

1) 使另一个 table(自连接)可见,以查看在不使用 where 子句连接时实际获得的结果:

select A.contactid, A.company, A.contact, B.contactid, B.company, B.contact from contacts A inner join contacts B on A.company = B.company

2) 现在添加你的 WHERE 子句并交换 A.contact 和 B.contact 看看会发生什么