连接3个表并同时获取零值(sql server)

连接3个表并同时获取零值(sql server),sql,sql-server,join,union,Sql,Sql Server,Join,Union,我对SQL Server有点陌生,我的目标是通过连接3个表来创建一个视图 只是一点背景: 首先,我只需要连接两个表(事实表有日期),我的主要目标是使用WEEKPART获取周数和相应的值。然而,我注意到可能会有这样一种情况:一年的第一周不会从1月1日开始。所以我决定有一个日历表,并将它与其他两个表连接起来 我有以下表格、记录和书籍类型: Create table Book_Type( ID int IDENTITY primary key, Name varchar(100) ); c

我对SQL Server有点陌生,我的目标是通过连接3个表来创建一个视图

只是一点背景: 首先,我只需要连接两个表(事实表有日期),我的主要目标是使用WEEKPART获取周数和相应的值。然而,我注意到可能会有这样一种情况:一年的第一周不会从1月1日开始。所以我决定有一个日历表,并将它与其他两个表连接起来

我有以下表格、记录和书籍类型:

Create table Book_Type(
  ID int IDENTITY  primary key,
  Name varchar(100)
);

create table Records(
  ID int IDENTITY  primary key,
  PurchDate date,
  BookName varchar(100),
  Book_TypeID int references Book_Type(id),
  Amt decimal(5,2)
);

insert into Book_Type values ('A'), ('B'), ('C'), 
                                ('D'), ('E');
insert into Records values  
                            ('20200107', 'Book1', 1, 56.23),
                            ('20200401', 'Book 99', 3, 195.09),
                            ('20200917', 'Book 54', 4, 522.9),
                            ('20200109', 'Book 34', 5, 604.32),
                            ('20200106', 'Book 22', 1, 881.4),
                            ('20200222', 'Book 14', 1, 355.66),
                            ('20200924', 'Book 70', 1, 920.44),
                            ('20201129', 'Book 12', 1, 344.86),
                            ('20200220', 'Book 38', 3, 676.5);

当我对三个表进行内部联接时,会得到ff结果: 代码:

结果:

 Week   Year    BookType    TotalAmt
    2       2020    A           937.63
    2       2020    E           604.32
    8       2020    A           355.66
    8       2020    C           676.50
    14      2020    C           195.09
    38      2020    D           522.90
    39      2020    A           920.44
    48      2020    A           344.86
我对结果没意见,但是,我想要的是也显示BookType为零值的周数。我仍然在考虑得到内部连接,并且有一个带有左外部连接的联合(结果显示为零值),但是我不知道如何得到它

我的期望是:

Week    Year    BookType    TotalAmt
1       2020    A           0
1       2020    B           0
1       2020    C           0
1       2020    D           0
1       2020    E           0
2       2020    A           937.63
2       2020    B           0
2       2020    C           0
2       2020    D           0
2       2020    E           604.32
3       2020    A           0
3       2020    B           0
3       2020    C           0
3       2020    D           0
3       2020    E           0
4       2020    A           0
4       2020    B           0
4       2020    C           0
4       2020    D           0
4       2020    E           0
5       2020    A           0
5       2020    B           0
5       2020    C           0
5       2020    D           0
5       2020    E           0
6       2020    A           0
6       2020    B           0
6       2020    C           0
6       2020    D           0
6       2020    E           0
7       2020    A           0
7       2020    B           0
7       2020    C           0
7       2020    D           0
7       2020    E           0
1       2020    A           0
8       2020    A           355.66
8       2020    B           0
8       2020    C           676.50
8       2020    D           0
8       2020    E           0
and so on, so forth..
14      2020    C           195.09
38      2020    D           522.90
39      2020    A           920.44
48      2020    A           344.86
我需要得到类型和周的零值,因为一旦我实现了这一点,我必须将它们相加。为了无缝地添加它们,即使总金额为0,也必须有一行


感谢您的帮助。谢谢大家!

您需要在日历表和书籍类型之间进行
交叉联接。这将生成行。然后使用
左联接
引入现有数据并聚合:

select c.Week, c.Year, b.Name as BookType,
       SUM(r.Amt) as TotalAmt
from Testdb.Auxiliary.Calendar c cross join
     Book_Type b left join
     Records r
     on b.ID = r.Book_TypeID and
        c.Day = DAY(r.PurchDate) and
        c.Month = MONTH(r.PurchDate) and
        c.Year = YEAR(r.PurchDate)
group by c.Week, c.Year, b.Name
order by c.Week, c.Year, b.Name asc;
我希望“Calendar”表有一个日期列,这样您就可以在日期而不是日期部分加入


另外,在英语中,
r
是名为
Records
的表的更合理的表别名。当然,在实际数据库中,
a
也可能是合理的别名。关键的想法是使用表格缩写,而不是任意字母。

改变你所做的事情的顺序,使用
BookType
Calendar
创建你想要的所有行的“模板”,然后
左连接
模板上的
记录

SELECT
  c.Week,
  c.Year,
  b.Name as BookType,
  COALESCE(SUM(a.Amt), 0)   AS TotalAmt
FROM
  Testdb.Auxiliary.Calendar as c
CROSS JOIN
  Book_Type as b
LEFT JOIN
  Records as a
    ON  b.ID     = a.Book_TypeID
    AND c.[Date] = a.PurchDate
WHERE
      c.[Date] >= '2020-01-01'
  AND c.[Date] <  '2021-01-01'
GROUP BY
  c.Week, c.Year, b.Name
ORDER BY
  c.Week, c.Year, b.Name
选择
c、 周,
c、 年,
b、 名称为BookType,
合并(总和(a.Amt),0)为总金额
从…起
Testdb.Auxiliary.Calendar作为c
交叉连接
b类图书
左连接
记录作为
在b.ID=a.Book\u TypeID上
c.[Date]=a.PurchDate
哪里
c、 [日期]>=“2020-01-01”
和c.[日期]<'2021-01-01'
分组
c、 周,c.年,b.姓名
订购人
c、 周,c.年,b.姓名

Testdb.Auxiliary.Calendar
开始,然后
左键加入
其余部分谢谢您的评论!我不熟悉交叉连接,所以我将首先研究它。是的,“日历”表有一个日期列(实际上是日期/时间列)。我会记住桌子的别名。由于网络上到处都有关于SQL Server的教程,我刚刚习惯了使用a、b、c等。谢谢!将尝试你的代码,并将返回给你的结果。
SELECT
  c.Week,
  c.Year,
  b.Name as BookType,
  COALESCE(SUM(a.Amt), 0)   AS TotalAmt
FROM
  Testdb.Auxiliary.Calendar as c
CROSS JOIN
  Book_Type as b
LEFT JOIN
  Records as a
    ON  b.ID     = a.Book_TypeID
    AND c.[Date] = a.PurchDate
WHERE
      c.[Date] >= '2020-01-01'
  AND c.[Date] <  '2021-01-01'
GROUP BY
  c.Week, c.Year, b.Name
ORDER BY
  c.Week, c.Year, b.Name