两个 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
,以及Order
和Delivery
的两个外键:OrderId
、DeliveryId
。
我想创建一个查询,让我大致了解每月的订单和交货数量,如下所示:
+------+-------+------------+---------------+
| 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的区别