Select 每个不同的 table 1 对于 table 2 的每个值

Select each distinct of table 1 for every value of table 2

我主要使用三个 table;第一个:Month/Year 日历,第二个:客户数据(与自身有 parent/child 关系),第三个:销售数据。我希望能够显示某个日期范围内每个月每个客户的销售额,而不管一个或多个客户可能没有销售额的月份。

我可以查询以显示范围内的每个 month/year,并计算带有销售额的月份的总销售额。但是,由于帐号通过没有每个月值的 table 加入日历,我不知道如何列出销售额为空的帐户。

到目前为止我最接近的:

with cumulative as (
select MONTH(s.docdate) [Month]
, YEAR(s.docdate) [Year]
, s.account [Account]
, sum(s.amount) [sales]
from sales s
group by MONTH(s.docdate), YEAR(s.docdate), s.account
)

select c.monthno [Month]
, c.year [Year]
, (select account from customers where account=s.account) [Account]
, s.sales
from cumulative s
right join calendar c
on datefromparts(s.year, s.month, 1) = datefromparts(c.year,c.monthno,1)
order by c.year, c.monthno

导致;

Month Year Account sales
1 2020 1 25
1 2020 2 90
2 2020 null null
3 2020 3 45
3 2020 4 65
4 2020 null null
5 2020 1 120
5 2020 2 45
6 2020 null null
7 2020 null null
etc.

示例设置在这里:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=b8ae260f2901693bf4cca75fb2451649

如果我尝试使用左联接或右联接来引入客户 table,会将结果折叠为仅具有销售值的月份和帐户。

with cumulative as (
select MONTH(s.docdate) [Month]
, YEAR(s.docdate) [Year]
, s.account [Account]
, sum(s.amount) [sales]
from sales s
group by MONTH(s.docdate), YEAR(s.docdate), s.account
)

select c.monthno [Month]
, c.year [Year]
, c2.account [Account]
, s.sales
from cumulative s
right join calendar c
on datefromparts(s.year, s.month, 1) = datefromparts(c.year,c.monthno,1)
right join customers c2
on s.account=c2.account

order by c.year, c.monthno

给出:

Month Year Account sales
1 2020 1 25
1 2020 2 90
3 2020 3 45
3 2020 4 65
5 2020 2 45
5 2020 1 120
1 2021 2 75

我希望看到的输出:

Month Year Account sales
1 2020 1 25
1 2020 2 90
1 2020 3 null
1 2020 4 null
2 2020 1 null
2 2020 2 null
2 2020 3 null
2 2020 4 null

如何让客户的每个帐号显示在日历中的每个月?

如果您将日历和客户与交叉联接结合起来,您将获得一组完整的帐户和日期。将其作为 CTE,然后使用您的 Cumulative CTE 来收集这些结果。现在您可以 select 来自 Calendar/Customers table 与销售数据的左联接:

with BaseTable
as (
select c.MonthNo as Month
     , c.Year
     , cust.Account
from [CALENDAR] c
cross join Customers cust
), cumulative as (
select MONTH(s.docdate) [Month]
, YEAR(s.docdate) [Year]
, s.account [Account]
, sum(s.amount) [sales]
from sales s
group by MONTH(s.docdate), YEAR(s.docdate), s.account
)
select bt.Month
     , bt.Year
     , bt.Account
     , c.sales
  from BaseTable bt
left join cumulative c
on c.month = bt.Month
and c.Year = bt.Year
and c.Account = bt.Account