结合左外连接和内连接 + 聚合函数 - 空结果集问题

Posted

技术标签:

【中文标题】结合左外连接和内连接 + 聚合函数 - 空结果集问题【英文标题】:Combining Left Outer and Inner Joins + Aggregate Function - Empty result set issue 【发布时间】:2021-11-07 09:30:44 【问题描述】:

这可能很简单,但我目前还没有看到。尝试组合左外连接和内连接,以便从给定的一组表中获取任何可用的信息,所有信息都与 customer_id 相关

示例在设计上可能并不完美(我是根据我的实际查询编写的),但足以说明我的问题,即使其中一些表中有行,它也是一个空结果集。

示例表:

简介:

id_profile   nm_profile 
-----------  ----------  
1234         User profile     

订单:

id_order id_customer order_date    order_type
-------  ----------  ---------     ----------     
10308    1234        2017-09-18    Online
10309    1234        2018-09-18    Online 

评论:

   id_review  id_profile   id_order   text    score   
   ---------  ----------   --------   -----   ------
   (no rows for this id_profile)

查询:

SELECT c.id_customer, MIN(o.order_date) order_date, r.text review_text
FROM Customer c
JOIN Profile p ON c.id_customer = p.id_profile 
LEFT OUTER JOIN Orders o ON o.id_customer = c.id_customer AND o.order_type = 'Online'
LEFT OUTER JOIN Reviews r ON r.id_reviewer = p.id_profile AND r.score = 5
WHERE c.id_customer = 1234
GROUP BY c.id_customer

假设这些列匹配并且我能够运行上述查询,我​​正在尝试实现以下目标:

id_customer    order_date   review_text
-----------    ----------   -----------
1234           2017-09-18   <NULL>

这是一个更大的查询的一部分;试图将其分解为最基本的表达方式,以了解我可能做错了什么。已尝试避免连接中的 WHERE 子句,还尝试了 LEFT OUTER JOIN (SELECT ....) ,但没有运气。

提前致谢!

【问题讨论】:

你写JOIN Profile p ON c.id_customer = p.id_profile的时候是指JOIN Profile p ON c.id_customer = p.id_customer吗? r.text 需要在 GROUP BY 中或者是 SELECT 中聚合函数的一部分 @jason44107 我的意思是 id_profile 的值与 id_customer 的值相关(不幸的是,我的真实示例有这些怪癖)编辑示例使其更具可读性,谢谢! 您的查询在 TSQL 或 Sybase 中都不起作用,因为 group by 子句和 select 列不一致。此外,您应该只标记您真正使用的数据库。如果有多个评论,你想要什么? 假设您在Sybase 数据库上运行... Sybase RDBMS 产品(ASE?IQ?SQLAnywhere?Advantage?)和版本? 【参考方案1】:

聚合完成后你应该加入Reviews

SELECT t.id_customer, t.order_date, r.text review_text
FROM ( 
  SELECT c.id_customer, MIN(o.order_date) order_date
  FROM Customer c
  INNER JOIN Profile p ON c.id_customer = p.id_profile 
  LEFT JOIN Orders o ON o.id_customer = c.id_customer AND o.order_type = 'Online'
  WHERE c.id_customer = 1234
  GROUP BY c.id_customer
) t
LEFT JOIN Reviews r ON r.id_reviewer = t.id_customer AND r.score = 5;

请参阅demo。

【讨论】:

【参考方案2】:

如果你只想要最大订单日期的所有评论信息,那么你可以总结orders表并加入其余部分:

SELECT c.id_customer, o.min_order_date, r.text as review_text
FROM Customer c JOIN
     Profile p ON c.id_customer = p.id_profile LEFT JOIN
     (SELECT o.id_customer, MIN(o.order_date) as min_order_date
      FROM Orders o
      WHERE o.order_type = 'Online'
      GROUP BY o.id_customer
     ) o
     ON o.id_customer = c.id_customer LEFT JOIN 
     Reviews r
     ON r.id_reviewer = p.id_profile AND r.score = 5
WHERE c.id_customer = 1234;

如果id_customer 有多个评论,这将返回多行。您的问题没有说明如何处理。

【讨论】:

以上是关于结合左外连接和内连接 + 聚合函数 - 空结果集问题的主要内容,如果未能解决你的问题,请参考以下文章

MySQL连接查询 内连接和外连接的区别

Linq To Sql 左外连接 - 过滤空结果

左外连接和空值转换

SQL中内连接和外连接的区别

SQL内连接与外连接的区别

左外连接和右外连接的区别