【问题标题】:Different in results from query between query and join查询和连接的查询结果不同
【发布时间】:2020-10-07 14:34:32
【问题描述】:

您好,有这两张桌子:

#客户

cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email
'1000000001', 'Village Toys', '200 Maple Lane', 'Detroit', 'MI', '44444', 'USA', 'John Smith', 'sales@villagetoys.com'
'1000000002', 'Kids Place', '333 South Lake Drive', 'Columbus', 'OH', '43333', 'USA', 'Michelle Green', NULL
'1000000003', 'Fun4All', '1 Sunny Place', 'Muncie', 'IN', '42222', 'USA', 'Jim Jones', 'jjones@fun4all.com'
'1000000004', 'Fun4All', '829 Riverside Drive', 'Phoenix', 'AZ', '88888', 'USA', 'Denise L. Stephens', 'dstephens@fun4all.com'
'1000000005', 'The Toy Store', '4545 53rd Street', 'Chicago', 'IL', '54545', 'USA', 'Kim Howard', NULL

#Orders

order_num, order_date, cust_id
'20005', '2012-05-01 00:00:00', '1000000001'
'20006', '2012-01-12 00:00:00', '1000000003'
'20007', '2012-01-30 00:00:00', '1000000004'
'20008', '2012-02-03 00:00:00', '1000000005'
'20009', '2012-02-08 00:00:00', '1000000001'

现在,如果我在一个字段上使用子查询执行这个查询,称为订单:

SELECT cust_name, 
       cust_state, 
       (SELECT COUNT(*) 
        FROM Orders 
        WHERE Orders.cust_id = Customers.cust_id) AS orders 
FROM Customers 
ORDER BY cust_name;

我收到订单 0 的“Kids Place”:

cust_name, cust_state, orders
'Fun4All', 'IN', '1'
'Fun4All', 'AZ', '1'
'Kids Place', 'OH', '0'
'The Toy Store', 'IL', '1'
'Village Toys', 'MI', '2'

但如果我使用加入版:

SELECT c.cust_name, 
   c.cust_state,
    COUNT(*) orders
FROM Customers c 
INNER JOIN Orders o
ON o.cust_id = c.cust_id
GROUP BY o.cust_id
ORDER BY c.cust_name;

我没有得到“儿童场所”行:

cust_name, cust_state, orders
'Fun4All', 'IN', '1'
'Fun4All', 'AZ', '1'
'The Toy Store', 'IL', '1'
'Village Toys', 'MI', '2'

为什么我会出现这种行为?

【问题讨论】:

  • 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)的 SQL,并以表格格式作为代码输入。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你所期望的,说出你所期望的以及为什么。
  • 如果您没有说明为什么您期望得到您所期望的结果,并根据权威文档说明理由,那么您只是要求我们用定制的教程重写它,而不知道您的误解是什么。这还不够集中。

标签: sql join subquery


【解决方案1】:

“INNER JOIN”只会​​返回在连接两侧找到的结果(想象一下维恩图中的重叠区域)。因为没有 Kids Place 的订单,所以连接中没有重叠,因此没有返回结果。

如果您想使用联接对您的子查询进行类似的查询,那么您会看到 LEFT JOIN。左连接将显示左侧的所有结果(在您的情况下为客户),然后尝试从右侧连接相应的结果(在您的情况下为订单)。

SELECT cust_name, 
       cust_state, 
       count(o.cust_id) as orders
FROM Customers c
LEFT JOIN Orders o on o.cust_id = c.cust_id
GROUP BY cust_name, cust_state;

sqlfiddle 上的示例

【讨论】:

  • 是的,但是怎么做?如果我使用 LEFT JOIN 代替 INNER ,我会得到错误。
  • 谢谢,我想研究您的解决方案,以更好地了解这两个查询之间的差异。
  • 另一件事:哪种写法更好?
  • 这取决于:) 一般来说,您使用的数据库会在后台对连接进行各种优化;然而,由于提高了可读性,很多人更喜欢子查询 - 调试具有许多连接的查询可能是一个令人沮丧的练习。查看查询的执行计划将使您更深入地了解查询的性能,并有助于确定联接或子查询是否更好。
  • 请原谅我的另一件事:如果我只按 cust_name 进行查询,为什么会出现错误并且我也需要使用 cust_state?
【解决方案2】:

您需要LEFT JOIN 才能使两者相等:

SELECT c.cust_name, c.cust_state,
       COUNT(o.cust_id) as orders
FROM Customers c LEFT JOIN
     Orders o
     ON o.cust_id = c.cust_id
GROUP BY c.cust_id
ORDER BY c.cust_name;

另请注意,COUNT() 已更改为计算匹配数。

【讨论】:

  • 我试过了,但它不起作用。我收到一个错误:错误代码:1055。SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含在功能上不依赖于 GROUP BY 子句中的列的非聚合列“tysql.c.cust_name”;
  • 这是错误的,因为查询没有按 c.cust_name、c.cust_state 分组。 Select 语句中的字段(聚合函数中的字段除外)应在 group by 子句中
  • 你能修复这个例子吗?
  • @Hyruma92 。 . .它(现在)由c.cust_id 聚合。完全有理由认为这是主键,在这种情况下,可以从同一个表中选择其他列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多