两个 INNER JOIN 的 FULL OUTER JOIN

Posted

技术标签:

【中文标题】两个 INNER JOIN 的 FULL OUTER JOIN【英文标题】:FULL OUTER JOIN of two INNER JOINs 【发布时间】:2021-02-02 13:38:33 【问题描述】:

我有三张桌子。 我的表Order 有一个Id 和一个Date。 同样,我的表Delivery 有一个Id 和一个Date。 我的第三张表Part 有一个Id,以及OrderDelivery 的两个外键:OrderIdDeliveryId

我想创建一个查询,让我大致了解每月的订单和交货数量,如下所示:

+------+-------+------------+---------------+
| Year | Month | OrderCount | DeliveryCount |
+------+-------+------------+---------------+
| 2021 | 2     | 10         | 12            |
+------+-------+------------+---------------+
| 2021 | 1     | 234        | 213           |
+------+-------+------------+---------------+
| ...  | ...   | ...        | ...           |
+------+-------+------------+---------------+

所以我创建了一个查询,该查询为我提供每月订单:

SELECT 
  MONTH(o.[Date]) AS [Month],
  YEAR(o.[Date]) AS [YEAR],
  COUNT(p.Id) AS OrderCount
FROM           
  Part AS p
INNER JOIN
  [Order] AS o ON o.Id = p.OrderId
GROUP BY 
  MONTH(o.[Date]), YEAR(o.[Date])

还有一个用于每月交货:

SELECT 
  MONTH(d.[Date]) AS [Month],
  YEAR(d.[Date]) AS [YEAR],
  COUNT(p.Id) AS DeliveryCount
FROM           
  Part AS p
INNER JOIN
  Delivery AS d ON d.Id = p.DeliveryId
GROUP BY 
  MONTH(d.[Date]), YEAR(d.[Date])

但现在我正在努力加入他们。我想我需要一个FULL OUTER JOIN,因为当没有订单但交货时我需要 Month/Year/DeliveryCount,反之亦然。

我试过的是

SELECT 
  MONTH(o.Date) AS [Month]
  YEAR(o.Date) as [Year]
  COUNT(p.Id) as OrderCount
FROM           
  Part AS p
INNER JOIN
  [Order] AS o ON o.Id = p.OrderId
GROUP BY 
MONTH(o.Date), Year(o.Date)

FULL OUTER JOIN

(SELECT 
  MONTH(d.Date) AS [Month]
  YEAR(d.Date) as [Year]
  COUNT(pp.Id) as DeliveryCount
FROM           
  Part AS pp
INNER JOIN
  Delivery AS d ON d.Id = pp.DeliveryId
GROUP BY 
MONTH(d.Date), YEAR(d.Date)) AS d ON d.[Month] = MONTH(o.Date) AND d.[Year] = YEAR(o.Date)

但这不是FULL OUTER JOINS 的工作方式。

如何获得这两个内连接的完整外连接? 或者这种外部连接两个内部连接的方法首先是错误的?

【问题讨论】:

样本数据和期望的结果真的很有帮助。某种 SQL/DB 小提琴将是一个很大的好处。我也不清楚“部分”表与 每月订单 的关系。 您有很多问题。首先,您的个人查询如何在列之间没有逗号的情况下运行?每当我构建更复杂的查询时,我总是确保较小的查询正常工作并首先返回我期望的数据。您的问题是您对待订单和交货的方式不同。您需要为您的 Orders 查询加上别名,就像您使用 Deliveries 查询一样。 抱歉,我在运行中将我的真实代码翻译成不那么具体、更通用且更易于理解的东西。我不小心犯了一些错误,比如缺少逗号。 【参考方案1】:

您必须将您的两个查询视为子查询。 这应该会给你想要的结果

 Select Orders.OrderCount, Deliveries.DeliveryCount
    from (
    SELECT 
      MONTH(o.Date) AS [Month]
      YEAR(o.Date) AS [YEAR]
      COUNT(p.Id) AS OrderCount
    FROM           
      Part AS p
    INNER JOIN
      [Order] AS o ON o.Id = p.OrderId
    GROUP BY 
      MONTH(o.Date), YEAR(o.Date)
    ) Orders

 

    FULL OUTER JOIN
    
    (
    SELECT 
      MONTH(d.Date) AS [Month]
      YEAR(d.Date) AS [YEAR]
      COUNT(p.Id) AS DeliveryCount
    FROM           
      Part AS p
    INNER JOIN
      Delivery AS d ON d.Id = p.DeliveryId
    GROUP BY 
      MONTH(d.Date), YEAR(d.Date) ) Deliveries
    

    on Orders.Month = Deliveries.Month
        and Orders.Year = Deliveries.Year

【讨论】:

@herrwolken 请注意代码的格式如何使阅读和理解变得更容易。这是一个要养成的好习惯。 @SMor,是的,我会尝试改进(进一步)。仍在研究最好的方法。 大多数编程语言都有一个(python.org/dev/peps/pep-0008、docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…、golang.org/doc/effective_go.html)风格指南,而对于 SQL,我发现了多种对如何格式化命令有不同想法的风格指南。【参考方案2】:

这将解决您的问题。 如果您缺少月份/年份,请使用其他联接。

WITH OrdersMonth AS (
SELECT 
  MONTH(o.Date) AS [Month]
  YEAR(o.Date) AS [YEAR]
  COUNT(p.Id) AS OrderCount
FROM           
  Part AS p
INNER JOIN
  [Order] AS o ON o.Id = p.OrderId
GROUP BY 
  MONTH(o.Date), YEAR(o.Date)
), DeliveriesMonth AS (
SELECT 
  MONTH(d.Date) AS [Month]
  YEAR(d.Date) AS [YEAR]
  COUNT(p.Id) AS DeliveryCount
FROM           
  Part AS p
INNER JOIN
  Delivery AS d ON d.Id = p.DeliveryId
GROUP BY 
  MONTH(d.Date), YEAR(d.Date)
)

SELECT om.YEAR
      ,om.Month
      ,om.OrderCount
      ,dm.DeliveryCount
 FROM OrdersMonth om
      LEFT JOIN DeliveriesMonth dm ON om.om.YEAR = dm.YEAR AND om.Month = dm.Month

【讨论】:

以上是关于两个 INNER JOIN 的 FULL OUTER JOIN的主要内容,如果未能解决你的问题,请参考以下文章

Mysql 连接(left join, right join, inner join ,full join)

SQL表连接查询(inner join(join)full joinleft joinright join)

SQL-连接查询:left join,right join,inner join,full join之间的区别

Oracle表与表之间的连接方式(内连接:inner join 外连接 全连接: full outer join左连接:left outer join 右连接:right outer join(代码

sql中 INNER JOIN LEFT JOIN RIGHT JOIN FULL JOIN 中 ON与Where的区别

sql中 INNER JOIN LEFT JOIN RIGHT JOIN FULL JOIN 中 ON与Where的区别