我的MasterSales
表看起来像这样
SalesDate | Category | Total
-----------------------------
1/1/2000 01 100
1/1/2000 02 110
1/2/2000 01 80
1/2/2000 03 20
我的Category
表看起来像这样
ID | Name ---------- 01 | A 02 | B 03 | C 04 | D
我的查询如下:
SELECT m.SalesDate, c.Name, SUM(ISNULL(m.Total,0)) AS TotalSales
FROM MasterSales m
LEFT JOIN Category c ON c.ID = m.Category
WHERE m.SalesDate BETWEEN '1/1/2000' AND '1/2/2000'
我想要的结果是这样的:
SalesDate | Name | TotalSales
------------------------------
1/1/2000 A 100
1/1/2000 B 110
1/1/2000 C 0
1/1/2000 D 0
1/2/2000 A 80
1/2/2000 B 0
1/2/2000 C 20
1/2/2000 D 0
但我得到的结果看起来是这样的:
SalesDate | Name | TotalSales
------------------------------
1/1/2000 A 100
1/1/2000 B 110
1/2/2000 A 80
1/2/2000 C 20
我已尝试使用RIGHT JOIN
代替LEFT JOIN
并在FROM
子句上切换表格,但结果仍然相同。任何人都可以帮我解释为什么它不能正常工作?
P.S。 :我正在使用SQL Server 2005(如果重要)
答案 0 :(得分:2)
试试这个。这包括您拥有 MasterSales 的所有日期。换句话说,这填补了当天缺失的类别。但是,您也希望填写缺少的日期,您需要创建日期控制表..查看 recursive cte 了解日期表
;with control_table as (
select distinct SalesDate, ID
from MasterSales ms
cross join Category c
where ms.SalesDate between '1/1/2000' AND '1/2/2000'
)
select ct.SalesDate, c.Name as Category, coalesce(sum(ms.Total),0) as Total
from control_table ct
inner join Category c
on ct.ID = c.ID
left join MasterSales ms
on ct.SalesDate = ms.SalesDate
and ct.ID = ms.Category
group by ct.SalesDate, c.Name
order by ct.SalesDate asc, c.Name asc
<强> FIDDLE 强>
答案 1 :(得分:2)
这是我的回答
WITH MasterSales (SalesDate, Category, Total) AS (
SELECT '1/1/2000','01',100
UNION SELECT '1/1/2000','02',110
UNION SELECT '1/2/2000','01',80
UNION SELECT '1/2/2000','03',20
), Category (ID, Name) AS (
SELECT '01','A'
UNION SELECT '02','B'
UNION SELECT '03','C'
UNION SELECT '04','D'
), getDates AS (
SELECT DISTINCT SalesDate
FROM MasterSales
WHERE SalesDate BETWEEN '1/1/2000' AND '1/2/2000'
)
SELECT gD.SalesDate, C.Name, SUM(ISNULL(MS.Total,0)) AS TotalSales
FROM getDates AS gD
CROSS JOIN Category AS C
LEFT JOIN MasterSales AS MS
ON MS.Category = C.ID
AND MS.SalesDate = gD.SalesDate
GROUP BY gD.SalesDate, C.Name
答案 2 :(得分:1)
最后,你的问题解决了。使用此查询:
SELECT AAA.SalesDate,AAA.Name,ISNULL(BBB.TotalSales,0) as TotalSales
FROM (
(SELECT m.SalesDate, c.Name
FROM MasterSales m,Category c
WHERE m.SalesDate BETWEEN '1/1/2000' AND '1/2/2000'
GROUP BY m.SalesDate,c.Name) AAA
LEFT JOIN
(SELECT m.SalesDate,c.Name, SUM(ISNULL(m.Total,0)) AS TotalSales
FROM MasterSales m,Category c
WHERE m.SalesDate BETWEEN '1/1/2000' AND '1/2/2000'
AND c.ID=m.Category
GROUP BY m.SalesDate,c.Name) BBB
on AAA.SalesDate=BBB.SalesDate AND AAA.Name=BBB.Name)
<强>解释强>
查询的第一部分(AAA)选择SalesDate
和Category
的所有组合。
查询的第二部分(BBB)选择SalesDate
,Category
和TotalSales
。
然后我们在SalesDate
和Category
加入他们(AAA和BBB)。
完美的工作!!!请参阅SQL Fiddle。
答案 3 :(得分:0)
更新:更改了使用sam yi
logic创建临时表的方法
我建议你创建一个附加表。
;WITH control_table AS (
SELECT DISTINCT SalesDate, Name
FROM MasterSales ms
CROSS JOIN Category c
)
SELECT d.SalesDate,
c.name,
COALESCE(sum(m.total),0) totalsales
FROM control_table d
LEFT OUTER JOIN Category c
ON d.Name = c.name
LEFT OUTER JOIN MasterSales m
ON (c.id = m.category
AND d.SalesDate = m.salesdate)
WHERE d.SalesDate BETWEEN '1/1/2000'
AND '1/2/2000'
GROUP BY
d.SalesDate,
c.name
ORDER BY
d.SalesDate,
c.name;
答案 4 :(得分:-1)
SELECT cj.Date, cj.Name, IsNull(m.Total,0) Total
FROM (SELECT d.Date, c.Name, c.Id
FROM (SELECT DISTINCT SalesDate Date
FROM MasterSales) d, Category c) cj
LEFT JOIN MasterSales m ON m.SalesDate = cj.Date
AND cj.Id = m.Category
http://www.sqlfiddle.com/#!3/d1344/3
添加日期条件
我确信有更好的方法可以做到这一点。
干杯