【发布时间】:2021-03-24 13:25:21
【问题描述】:
我正在研究一家大型零售店的数据库。 我必须从多个表中查询数据以获取收入、原始收益等数字并比较不同的时间段。 其中大部分都很容易,但我一直在努力寻找一种加入多个 CTE 的方法。 我做了一个小提琴,所以你知道我在说什么。 我大大简化了结构,并在子查询中省略了很多列,因为在这种情况下它们无关紧要。
如您所见,每个表格中的每一行都包含国家和品牌。 最终查询必须按这些分组。 我首先尝试的是 FULL JOIN 所有表,但在某些情况下这不起作用,如您在此处看到的:SQLfiddle #1。注意最后两行没有正确分组。
Select Coalesce(incoming.country, revenue.country, revcompare.country,
openord.country) As country,
Coalesce(incoming.brand, revenue.brand, revcompare.brand,
openord.brand) As brand,
incoming.OrdersNet,
openord.OpenOrdersNet,
revenue.Revenue,
revenue.RawProceeds,
revcompare.RevenueCompare,
revcompare.RawProceedsCompare
From incoming
Full Join openord On openord.country = incoming.country And
openord.brand = incoming.brand
Full Join revenue On revenue.country = incoming.country And
revenue.brand = incoming.brand
Full Join revcompare On revcompare.country = incoming.country And
revcompare.brand = incoming.brand
Group By incoming.OrdersNet,
openord.OpenOrdersNet,
revenue.Revenue,
revenue.RawProceeds,
revcompare.RevenueCompare,
revcompare.RawProceedsCompare,
incoming.country,
revenue.country,
openord.country,
revcompare.country,
incoming.brand,
revenue.brand,
revcompare.brand,
openord.brand
Order By country,
brand
然后我重写了保留所有 CTE 的查询。我添加了另一个 CTE(基础),它结合了所有可能的国家和品牌组合,并加入了那个组合。 现在它工作正常(在这里查看 -> SQLfiddle #2)但它看起来很复杂。难道没有更简单的方法来实现这一点吗?我唯一可能无法更改的是 CTE,因为在现实生活中它们要复杂得多。
WITH basis AS (
SELECT Country, Brand FROM incoming
UNION
SELECT Country, Brand FROM openord
UNION
SELECT Country, Brand FROM revenue
UNION
SELECT Country, Brand FROM revcompare
)
SELECT
basis.Country,
basis.Brand,
incoming.OrdersNet,
openord.OpenOrdersNet,
revenue.Revenue,
revenue.RawProceeds,
revcompare.RevenueCompare,
revcompare.RawProceedsCompare
FROM basis
LEFT JOIN incoming On incoming.Country = basis.Country AND incoming.Brand = basis.Brand
LEFT JOIN openord On openord.Country = basis.Country AND openord.Brand = basis.Brand
LEFT JOIN revenue On revenue.Country = basis.Country AND revenue.Brand = basis.Brand
LEFT JOIN revcompare On revcompare.Country = basis.Country AND revcompare.Brand = basis.Brand
感谢大家的帮助!
【问题讨论】:
-
所以只是为了获得您想要的内容的高级摘要。您想要一个所有
Country+Brand组合的唯一列表,然后您想要加入来自incoming、openord、revenue、recompare的统计信息? -
另外,这个必须在单个查询中完成有什么原因吗?为清楚起见,如果您使用表变量或临时表,很多时候它会使代码更具可读性。
-
如果您在使用 CTE 时遇到困难,请恢复到临时表
-
注意最后两行没有正确分组是的,他们确实分组正确,因为这就是您编写查询的方式。最后的 group by 子句中有太多列。但这是一个有争议的问题,因为您的 CTE 只会为每个国家/品牌生产 1 行。最终查询根本不需要分组。
-
注意 - CTE 传入和 openord 可以使用条件求和合并为 1 以提高效率。收入和 revcompare 相同。
标签: sql sql-server tsql common-table-expression