隐式内连接如何处理多个WHERE子句条件

huangapple go评论70阅读模式
英文:

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=5customers 表中不存在。当我运行下面的查询时,它返回下面的结果。

查询:

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  

huangapple
  • 本文由 发表于 2023年4月17日 20:45:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76035299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定