我正在尝试制作一个这样的表:
产品名称| SalesByDate | TotalSalesUntilDate
A | 5 | 15 B | 10 | 30 C | 20 | 25 D | 18 | 43
SalesByDate表示在输入日期为每种产品销售的产品数量,TotalSalesUntilDate表示从每月的第一个日期到输入日期的每种产品的销售产品数量(输入日期的示例:2010年3月17日)< / p>
我使用子查询编写了这个查询:
select p.ProductName, A.SalesByDate,
(select(SUM(case when (pd.Date between '01' and @Date)
then s.SalesByDate else 0 end))
from Period pd
inner join Sales s on pd.TimeID = s.TimeID
full join Product p on s.ProductID = p.ProductID) as TotalSalesUntilDate
from Product p join
(select s.ProductID, pd.Date, s.SalesByDate
from Period pd join Sales s on pd.TimeID = s.TimeID) A on
p.ProductID = A.ProductID where @Date = A.Date
但我得到了结果:
产品名称| SalesByDate | TotalSalesUntilDate
A | 5 | 113 B | 10 | 113 C | 20 | 113 D | 18 | 113
其中TotalSalesUntilDate显示从月份的第一个日期到输入日期之间销售的产品数量,但是对于每个产品没有分离的所有产品。
所以,当我尝试将查询更改为这样时(在“作为TotalSalesUntilDate”之前添加GROUP BY p.ProductID):
select p.ProductName, A.SalesByDate,
(select(SUM(case when (pd.Date between '01' and @Date)
then s.SalesByDate else 0 end))
from Period pd
inner join Sales s on pd.TimeID = s.TimeID
full join Product p on s.ProductID = p.ProductID
group by p.ProductID) as TotalSalesUntilDate
from Product p join
(select s.ProductID, pd.Date, s.SalesByDate
from Period pd join Sales s on pd.TimeID = s.TimeID) A on
p.ProductID = A.ProductID where @Date = A.Date
当我执行此查询时,收到此错误消息:
“消息512,级别16,状态1,过程SalesMTDSubQuery,第7行 子查询返回的值超过1。这是不允许的 子查询跟随=,!=,&lt;,&lt; =,&gt;,&gt; =或当子查询用作 表达。“
由于我是SQL新手并且还在学习,但我不明白如何解决这个问题。任何帮助将不胜感激。谢谢。
答案 0 :(得分:3)
在@Date
变量中,我们存储日期:
SELECT DISTINCT PT.[ProductName]
,SUM(IIF(PD.[Date] = @Date, SL.[SalesByDate], 0))
,SUM(IIF(PD.[Date] BETWEEN '01' AND @Date, SL.[SalesByDate], 0))
FROM @Product PT
INNER JOIN @Sales SL
ON PT.[ProductID] = SL.[ProductID]
INNER JOIN @Period PD
ON SL.[TimeID] = PD.[TimeID]
GROUP BY PT.[ProductName]
结果:
完整代码:
DECLARE @Period TABLE
(
[TimeID] TINYINT
,[Date] CHAR(2)
)
INSERT INTO @Period([TimeID], [Date])
VALUES (1,'01')
,(2,'02')
,(3,'03')
,(4,'04')
,(5,'05')
,(6,'06')
,(7,'07')
,(8,'08')
,(9,'09')
,(10,'10')
,(11,'11')
,(12,'12')
,(13,'13')
,(14,'14')
,(15,'15')
DECLARE @Product TABLE
(
[ProductID] TINYINT
,[ProductName] CHAR(1)
)
INSERT INTO @Product( [ProductID], [ProductName])
VALUES (1,'A')
,(2,'B')
,(3,'C')
,(4,'D')
DECLARE @Sales TABLE
(
[TimeID] TINYINT
,[ProductID] TINYINT
,[SalesByDate] TINYINT
)
INSERT INTO @Sales ([TimeID], [ProductID], [SalesByDate])
VALUES (1, 1, 10)
,(1, 4, 20)
,(7, 2, 10)
,(7, 3, 5)
,(15, 1, 5)
,(15, 2, 10)
,(15, 3, 15)
,(15, 4, 18)
,(19, 2, 15)
,(20, 3, 2)
,(22, NULL, 2)
,(1, 4, 5)
,(7, 2, 10)
,(15, 3, 5)
DECLARE @Date CHAR(2) = '15'
SELECT DISTINCT PT.[ProductName]
,SUM(IIF(PD.[Date] = @Date, SL.[SalesByDate], 0))
,SUM(IIF(PD.[Date] BETWEEN '01' AND @Date, SL.[SalesByDate], 0))
FROM @Product PT
INNER JOIN @Sales SL
ON PT.[ProductID] = SL.[ProductID]
INNER JOIN @Period PD
ON SL.[TimeID] = PD.[TimeID]
GROUP BY PT.[ProductName]
编辑:
如果您需要使用子查询,这就是您的示例的工作方式:
SELECT PT.[ProductName]
,SUM(SL.[SalesByDate])
,DataSource.[TotalSalesByDate]
FROM @Product PT
INNER JOIN @Sales SL
ON PT.[ProductID] = SL.[ProductID]
INNER JOIN @Period PD
ON SL.[TimeID] = PD.[TimeID]
INNER JOIN
(
SELECT S.[ProductID]
,SUM(S.[SalesByDate]) AS [TotalSalesByDate]
FROM @Sales S
INNER JOIN @Period P
ON S.[TimeID] = P.[TimeID]
WHERE P.[Date] BETWEEN '01' AND @Date
GROUP BY S.[ProductID]
) AS DataSource
ON PT.[ProductID] = DataSource.[ProductID]
WHERE PD.[Date] = @Date
GROUP BY PT.[ProductName]
,DataSource.[TotalSalesByDate]
答案 1 :(得分:1)
首先,在Table Period
中,您必须有日期,而不是'01','02'
,因此您可以使用BETWEEN
。或者你可以使用1,2,3 ...
,但它们必须是数字。
因此,我们假设在表Table Period
中您有日期数字(我发表此评论,因为您使用01
,而不是1
,它假设字符串值。查询本身相对容易:
SELECT
p.ProductName,
SUM(CASE WHEN s.TimeID = 10 THEN s.SalesByDate ELSE 0 END) as SalesByDate,
SUM(CASE WHEN s.TimeID = 10 THEN 0 ELSE s.SalesByDate END) as TotalSalesUntilDate
FROM
Product p
INNER JOIN Salse s ON p.ProductID = s.ProductID
WHERE
s.TimeID BETWEEN 1 AND 10
GROUP BY p.ProductName;
您为每个日期获取销售额。如果这是选定日期,则将销售额添加到列SalesByDate
,否则添加到列TotalSalesUntilDate
。您按ProductName
分组以计算SUM
。并在WHERE
子句中仅选择所需期间的日期。我们假设此查询仅在特定月份启动(因为我们仅使用日期元素 - 即1,2,......而不是月份)。
这将仅显示具有销售额的产品。如果您想查看所有产品列表,请使用LEFT JOIN
代替INNER JOIN
。