英文:
How Implicit inner join works with multiple WHERE clause conditions
问题
通过显式内连接,我们指定来自两个表的共同列名称,并选择这些列中具有匹配值的记录。
通过 WHERE 子句使用隐式内连接,指定条件进行匹配。因此,我想了解如何在多个条件下进行连接,条件的顺序是否重要?
由于我有两个如下的表:
表1: Customers
customer_id | name | age |
---|---|---|
1 | John | 25 |
2 | Marry | 22 |
表2: Orders
order_id | amount | customer_id |
---|---|---|
1 | 100 | 1 |
2 | 200 | 5 |
orders
表中的 customer_id
字段存储了 customers
表的 customer_id
字段的值。不幸的是,我们在 orders
表的 customer_id
字段上没有任何外键约束。因此,如果查看上面的 orders
表,customer_id=5 在 customers
表中不存在。当我运行下面的查询时,它返回下面的结果。
查询:
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id = Orders.customer_id
AND Orders.amount >= 200;
结果:
Customers.customer_id | Orders.customer_id | Customers.name | Orders.amount |
---|---|---|---|
(null) | 5 | (null) | 200 |
所有来自 Orders
表的字段数据都被提取,而 customers
表的字段数据返回为空数据。但理论上,内连接只有在两个表都有匹配时才返回数据?
更新:
我为此真的很抱歉,但我刚刚在代码中注意到在 WHERE 子句的右侧有 (+),我之前将其排除在外,认为它没有用处,现在我知道它表示 RIGHT OUTER 连接。现在查询结果对我来说是有意义的。
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id = Orders.customer_id (+)
AND Orders.amount >= 200;
感谢 StackOverflow 社区,你们是最棒的!
英文:
With Explicit Inner join, we specify the common column names from both tables and it selects records that have matching values in these columns.
SELECT Customers.customer_id, Customers.name, Orders.amount
FROM Customers
INNER JOIN Orders
ON Customers.customer_id = Orders.customer_id
WHERE Orders.amount >= 200;
But with Implicit Inner join, we just use the WHERE clauses and specify the conditions to be the match. So I want to understand how joining works for multiple conditions, Does the order of conditions matter?
I am asking this because I have two tables like the below:-
Table1: Customers
customer_id | name | age |
---|---|---|
1 | John | 25 |
2 | Marry | 22 |
Table2: Orders
order_id | amount | customer_id |
---|---|---|
1 | 100 | 1 |
2 | 200 | 5 |
The customer_id
field in the orders
table stores the values of the customer_id
field of the customers
table. And unfortunately, we don't have any foreign key constraint on the customer_id
field of the orders
table. So if you see the above orders
table, the customer_id=5 doesn't exist in the customers
table and when I run the below query, it returns the below result.
Query:-
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id = Orders.customer_id
AND Orders.amount >= 200;
Result:-
Customers.customer_id | Orders.customer_id | Customers.name | Orders.amount |
---|---|---|---|
(null) | 5 | (null) | 200 |
All the field's data from the table Orders
is being fetched and the field's data for the customers
table is returned as empty data. But ideally inner join only returns the data if there is a match from both tables?
I might be misunderstanding something and clearing my basics.
Thanks for the help!
Update:
I really apologize for this but I just noticed in the code there is (+) on the right side of the WHERE clause which I was excluded thinking is of no use and now I came to know it denotes RIGHT OUTER join. And now the query results make sense to me.
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id = Orders.customer_id (+)
AND Orders.amount >= 200;
Thanks to the StackOverflow community, you are the best!
答案1
得分: 3
Your query:
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id = Orders.customer_id
AND Orders.amount >= 200;
然后,传统的逗号连接可以被替换为符合ANSI标准的CROSS JOIN
,与以下查询相同:
SELECT c.customer_id, o.customer_id, c.name, o.amount
FROM Customers c CROSS JOIN Orders o
WHERE c.customer_id = o.customer_id
AND o.amount >= 200;
而这又与以下查询相同:
SELECT c.customer_id, o.customer_id, c.name, o.amount
FROM Customers c
INNER JOIN Orders o
ON c.customer_id = o.customer_id
WHERE o.amount >= 200;
这与你的第一个查询相同。
条件的顺序重要吗?
不重要。
当我运行下面的查询时,它返回以下结果。
这个结果是不可能的,因为Customers.customer_id = Orders.customer_id
在输出中不成立,所以无法返回这样的结果。
英文:
Your query:
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id = Orders.customer_id
AND Orders.amount >= 200;
Then the legacy comma-join can be replaced with an ANSI-standard CROSS JOIN
and is the same as:
SELECT c.customer_id, o.customer_id, c.name, o.amount
FROM Customers c CROSS JOIN Orders o
WHERE c.customer_id = o.customer_id
AND o.amount >= 200;
Which, in turn, is the same as:
SELECT c.customer_id, o.customer_id, c.name, o.amount
FROM Customers c
INNER JOIN Orders o
ON c.customer_id = o.customer_id
WHERE o.amount >= 200;
Which is the same as your first query.
> Does the order of conditions matter?
No
> when I run the below query, it returns the below result.
That result is impossible as Customers.customer_id = Orders.customer_id
is not true in the output so the result cannot be returned.
答案2
得分: 2
以下是您要翻译的内容:
"Your query:
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id = Orders.customer_id
AND Orders.amount >= 200;
cannot produce the output you showed. This is an inner join, and since there is no matching customer_id = 5 in the customers table, it will not show the order record for customer_id 5 either. If you wanted to see it, you'd need an outer join:
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id(+) = Orders.customer_id
AND Orders.amount >= 200;
To answer your specific question, the order of join clauses does not matter, nor the order of columns in the join clause. Join predicates are treated the same as filter predicates and evaluated in any order Oracle pleases without changing the result. There's something wrong with your test. Please double-verify your SQL and its results."
英文:
Your query:
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id = Orders.customer_id
AND Orders.amount >= 200;
cannot produce the output you showed. This is an inner join, and since there is no matching customer_id = 5 in the customers table, it will not show the order record for customer_id 5 either. If you wanted to see it, you'd need an outer join:
SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
FROM Customers, Orders
WHERE Customers.customer_id(+) = Orders.customer_id
AND Orders.amount >= 200;
To answer your specific question, the order of join clauses does not matter, nor the order of columns in the join clause. Join predicates are treated the same as filter predicates and evaluated in any order Oracle pleases without changing the result. There's something wrong with your test. Please double-verify your SQL and its results.
答案3
得分: 1
你是否运行了自己的代码?它没有显示你发布的结果。
SQLcl: Release 22.4 Production on Mon Apr 17 15:10:13 2023
koen>CREATE TABLE customers (customer_id,name,age)
2 AS
3 (
4 SELECT 1, 'John', 25 FROM DUAL UNION ALL
5 SELECT 2, 'Marry', 22 FROM DUAL
6* );
Table CUSTOMERS created.
koen>CREATE TABLE orders (order_id,amount,customer_id)
2 AS
3 (
4 SELECT 1, 100, 1 FROM DUAL UNION ALL
5 SELECT 2, 200, 5 FROM DUAL
6* );
Table ORDERS created.
你的查询 - 使用传统连接语法。
koen>SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
2 FROM Customers, Orders
3 WHERE Customers.customer_id = Orders.customer_id(+)
4* AND Orders.amount >= 200;
no rows selected
相同的查询使用 ANSI 连接语法重写。
koen>SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
2 FROM Customers
3 JOIN Orders ON Customers.customer_id = Orders.customer_id
4* WHERE Orders.amount >= 200;
no rows selected
重写的查询以显示你所展示的结果 - 使用传统连接语法。
koen>SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
2 FROM Customers, Orders
3 WHERE Customers.customer_id(+) = Orders.customer_id
4* AND Orders.amount >= 200;
CUSTOMER_ID CUSTOMER_ID NAME AMOUNT
______________ ______________ _______ _________
5 200
相同的查询使用 ANSI 连接语法重写。
koen>SELECT customers.customer_id, orders.customer_id, customers.name, orders.amount
2 FROM orders
3 left outer JOIN customers ON customers.customer_id = orders.customer_id
4* WHERE orders.amount >= 200;
CUSTOMER_ID CUSTOMER_ID NAME AMOUNT
______________ ______________ _______ _________
5 200
英文:
Did you run your own code ? It doesn't show the results you posted.
SQLcl: Release 22.4 Production on Mon Apr 17 15:10:13 2023
koen>CREATE TABLE customers (customer_id,name,age)
2 AS
3 (
4 SELECT 1, 'John', 25 FROM DUAL UNION ALL
5 SELECT 2, 'Marry', 22 FROM DUAL
6* );
Table CUSTOMERS created.
koen>CREATE TABLE orders (order_id,amount,customer_id)
2 AS
3 (
4 SELECT 1, 100, 1 FROM DUAL UNION ALL
5 SELECT 2, 200, 5 FROM DUAL
6* );
Table ORDERS created.
Your query - using traditional join syntax.
koen>SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
2 FROM Customers, Orders
3 WHERE Customers.customer_id = Orders.customer_id(+)
4* AND Orders.amount >= 200;
no rows selected
same query rewritten using ANSI join syntax
koen>SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
2 FROM Customers
3 JOIN Orders ON Customers.customer_id = Orders.customer_id
4* WHERE Orders.amount >= 200;
no rows selected
Query rewritten to produce the results you display - using traditional join syntax.
koen>SELECT Customers.customer_id, Orders.customer_id, Customers.name, Orders.amount
2 FROM Customers, Orders
3 WHERE Customers.customer_id(+) = Orders.customer_id
4* AND Orders.amount >= 200;
CUSTOMER_ID CUSTOMER_ID NAME AMOUNT
______________ ______________ _______ _________
5 200
same query rewritten using ANSI join syntax
koen>SELECT customers.customer_id, orders.customer_id, customers.name, orders.amount
2 FROM orders
3 left outer JOIN customers ON customers.customer_id = orders.customer_id
4* WHERE orders.amount >= 200;
CUSTOMER_ID CUSTOMER_ID NAME AMOUNT
______________ ______________ _______ _________
5 200
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论