我有我的数据库表 ABC ,如下所示:
ItemId Month Year Sales
1 1 2013 333
1 2 2013 454
2 1 2013 434
等等。
我想写一个查询来查找从上个月到本月销售额增幅最高的前3个项目,以便我在输出中看到类似的内容。 输出:
ItemId IncreaseInSales
1 +121
9 +33
6 +16
我来到这里:
select
(select Sum(Sales) from ABC where [MONTH] = 11 )
-
(select Sum(Sales) from ABC where [MONTH] = 10)
我不能使用组,因为它给出了错误。任何人都可以指出我的方式 继续前进?
答案 0 :(得分:1)
假设您希望增加给定月份,您还可以使用聚合查询执行此操作:
select top 3 a.ItemId,
((sum(case when year = @YEAR and month = @MONTH then 1.0*sales end) /
sum(case when year = @YEAR and month = @MONTH - 1 or
year = @YEAR - 1 and @Month = 1 and month = 12
then sales end)
) - 1
) * 100 as pct_increase
from ABC a
group by a.ItemId
order by pct_increase desc;
您可以将您关心的年/月组合放在变量@YEAR
和@MONTH
中。
编辑:
如果你只是想要增加,那么就要有所作为:
select top 3 a.ItemId,
(sum(case when year = @YEAR and month = @MONTH then 1.0*sales end) -
sum(case when year = @YEAR and month = @MONTH - 1 or
year = @YEAR - 1 and @Month = 1 and month = 12
then sales
end)
) as difference
from ABC a
group by a.ItemId
order by difference desc;
答案 1 :(得分:0)
以下是演示以下查询的 SQL Fiddle :
SELECT TOP(3) NewMonth.ItemId,
NewMonth.Month11Sales - OldMonth.Month10Sales AS IncreaseInSales
FROM
(
SELECT s1.ItemId, Sum(s1.Sales) AS Month11Sales
FROM ABC AS s1
WHERE s1.MONTH = 11
AND s1.YEAR = 2013
GROUP BY s1.ItemId
) AS NewMonth
INNER JOIN
(
SELECT s2.ItemId, Sum(s2.Sales) AS Month10Sales
FROM ABC AS s2
WHERE s2.MONTH = 10
AND s2.YEAR = 2013
GROUP BY s2.ItemId
) AS OldMonth
ON NewMonth.ItemId = OldMonth.ItemId
ORDER BY NewMonth.Month11Sales - OldMonth.Month10Sales DESC
你从来没有提到过ItemId
是否有多个Month
的记录,所以我提出了查询来处理它。显然,您的查询中缺少year = 2013
。一旦你过了今年,你将需要它。
答案 2 :(得分:0)
您的示例数据似乎不完整,但是,这是我的尝试。我假设你想知道从一个月到下一个月销售差异最大的三个项目:
WITH Increases AS
(
SELECT a1.itemid,
a1.sales - (SELECT a2.sales
FROM dbo.abc a2
WHERE a1.itemid = a2.itemid
AND ( ( a1.year = a2.year
AND a1.month > 1
AND a1.month = a2.month + 1 )
OR ( a1.year = a2.year + 1
AND a1.month = 1
AND a2.month = 12 ) ))AS IncreaseInSales
FROM dbo.abc a1
)
SELECT TOP 3 ItemID, MAX(IncreaseInSales) AS IncreaseInSales
FROM Increases
GROUP BY ItemID
ORDER BY MAX(IncreaseInSales) DESC
答案 3 :(得分:0)
我这样做。它应该适用于所有标记的SQL Server版本:
SELECT TOP 3 [ItemId],
MAX(CASE WHEN [Month] = 2 THEN [Sales] END) -
MAX(CASE WHEN [Month] = 1 THEN [Sales] END) [Diff]
FROM t
WHERE [Month] IN (1, 2) AND [Year] = 2013
GROUP BY [ItemId]
HAVING COUNT(*) = 2
ORDER BY [Diff] DESC
小提琴here。
我添加HAVING
子句的原因是,如果只在其中一个月内添加任何项目,则数字将全部错误。所以我只是比较两个月才出现的项目。
WHERE
子句的原因是只提前过滤所需的月份并提高查询效率。
SQL Server 2012解决方案也可以是:
SELECT TOP 3 [ItemId], [Diff] FROM (
SELECT [ItemId],
LEAD([Sales]) OVER (PARTITION BY [ItemId] ORDER BY [Month]) - [Sales] Diff
FROM t
WHERE [Month] IN (1, 2) AND [Year] = 2013
) s
WHERE [Diff] IS NOT NULL
ORDER BY [Diff] DESC
答案 4 :(得分:0)
另一种选择可能就是这些问题:
SELECT top 3 a.itemid, asales-bsales increase FROM
(
(select itemid, month, sum(sales) over(partition by itemid) asales from ABC where month=2
and year=2013) a
INNER JOIN
(select itemid, month, sum(sales) over(partition by itemid) bsales from ABC where month=1
and year=2013) b
ON a.itemid=b.itemid
)
ORDER BY increase desc
如果您需要在没有销售的情况下满足数月,那么您可以进行全加入并计算增加为isnull(asales,0) - isnull(bsales,0)
答案 5 :(得分:0)
您可以根据PIVOT运算符调整此解决方案:
SET NOCOUNT ON;
DECLARE @Sales TABLE
(
ItemID INT NOT NULL,
SalesDate DATE NOT NULL,
Amount MONEY NOT NULL
);
INSERT @Sales (ItemID, SalesDate, Amount)
VALUES
(1, '2013-01-15', 333), (1, '2013-01-14', 111), (1, '2012-12-13', 100), (1, '2012-11-12', 150),
(2, '2013-01-11', 200), (2, '2012-12-10', 150), (3, '2013-01-09', 900);
-- Parameters (current year & month)
DECLARE @pYear SMALLINT = 2013,
@pMonth TINYINT = 1;
DECLARE @FirstDayOfCurrentMonth DATE = CONVERT(DATE, CONVERT(CHAR(4), @pYear) + '-' + CONVERT(CHAR(2), @pMonth) + '-01');
DECLARE @StartDate DATE = DATEADD(MONTH, -1, @FirstDayOfCurrentMonth), -- Begining of the previous month
@EndDate DATE = DATEADD(DAY, -1, DATEADD(MONTH, 1, @FirstDayOfCurrentMonth)) -- End of the current month
SELECT TOP(3) t.ItemID,
t.[2]-t.[1] AS IncreaseAmount
FROM
(
SELECT y.ItemID, y.Amount,
DENSE_RANK() OVER(ORDER BY y.FirstDayOfSalesMonth ASC) AS MonthNum -- 1=Previous Month, 2=Current Month
FROM
(
SELECT x.ItemID, x.Amount,
DATEADD(MONTH, DATEDIFF(MONTH, 0, x.SalesDate), 0) AS FirstDayOfSalesMonth
FROM @Sales x
WHERE x.SalesDate BETWEEN @StartDate AND @EndDate
) y
) z
PIVOT( SUM(z.Amount) FOR z.MonthNum IN ([1], [2]) ) t
ORDER BY IncreaseAmount DESC;
答案 6 :(得分:0)
SELECT
cur.[ItemId]
MAX(nxt.[Sales] - cur.[Sales]) AS [IncreaseInSales]
FROM ABC cur
INNER JOIN ABC nxt ON (
nxt.[Year] = cur.[Year] + cur.[month]/12 AND
nxt.[Month] = cur.[Month]%12 + 1
)
GROUP BY cur.[ItemId]