我想从sql查询中提取最近12个月的值。
问题是总结过去12个月,而不是整整一年。
所以当我在我的参数中选择2000年3月作为默认值时,
我希望查询得到补充:从1999年3月到2000年3月。
这是我到目前为止所得到的:
SELECT Name, SUM(sales) as totalsales, year_month
FROM Total_Sales
WHERE
(year_month = @year_month)
GROUP BY Name, year_month
感谢您的帮助!
- 编辑 -
SELECT Name, SUM(sales) as totalsales, year_month
FROM Total_Sales
WHERE
(year_month >= @From) AND
(year_month <= @To)
GROUP BY Name, year_month
在“Steve Morgan”的建议之后添加了这个
我们能否以某种方式添加过去12个月的平均值,而无需在参数中选择12个月。
让“@From”参数决定起始值。像:AVG(@From -12个月)??
再次感谢您的帮助!
- 编辑2 -
ROW_NUMBER()函数非常方便解决此问题。 我的查询现在看起来像这样:
SELECT Name, SUM(sales)
FROM
(
SELECT rn = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY year, year_month)
, Name
, sales = SUM(sales)
FROM Total_Sales ts
WHERE
(year_month>= @From) AND
(year_month<= @To)
GROUP BY
Name
, year
, year_month
) ts
WHERE
rn <= 12
GROUP BY
Name
答案 0 :(得分:3)
此代码比Steve Morgans长,但旨在让优化器能够使用year
和year_month
字段上的任何现有INDEX。这只有在你有一个相对较大的表时才有意义,因为它旨在有效地知道可以跳过哪些记录。
(它还假设MS SQL Server,但该逻辑适用于其他RDBMS。)
DECLARE
@DateParam AS DATETIME
SELECT
@DateParam = '2011 June 01'
;WITH MyTable (Name, Year, Year_Month, Sales) AS
(
SELECT 'Rod', 2010, 1, 10
UNION ALL SELECT 'Rod', 2010, 2, 10
UNION ALL SELECT 'Rod', 2010, 3, 10
UNION ALL SELECT 'Rod', 2010, 4, 10 UNION ALL SELECT 'Jane', 2010, 4, 10
UNION ALL SELECT 'Rod', 2010, 5, 10 UNION ALL SELECT 'Jane', 2010, 5, 10
UNION ALL SELECT 'Rod', 2010, 6, 10 UNION ALL SELECT 'Jane', 2010, 6, 10
------------------------------------------------------------------------------
UNION ALL SELECT 'Rod', 2010, 7, 10 UNION ALL SELECT 'Jane', 2010, 7, 10
UNION ALL SELECT 'Rod', 2010, 8, 10 UNION ALL SELECT 'Jane', 2010, 8, 10
UNION ALL SELECT 'Rod', 2010, 9, 10 UNION ALL SELECT 'Jane', 2010, 9, 10
UNION ALL SELECT 'Rod', 2010,10, 10 UNION ALL SELECT 'Jane', 2010,10, 10
UNION ALL SELECT 'Jane', 2010,11, 10
UNION ALL SELECT 'Jane', 2010,12, 10
UNION ALL SELECT 'Jane', 2011, 1, 10
UNION ALL SELECT 'Jane', 2011, 2, 10
UNION ALL SELECT 'Rod', 2011, 3, 10 UNION ALL SELECT 'Jane', 2011, 3, 10
UNION ALL SELECT 'Rod', 2011, 4, 10 UNION ALL SELECT 'Jane', 2011, 4, 10
UNION ALL SELECT 'Rod', 2011, 5, 10
UNION ALL SELECT 'Rod', 2011, 6, 10
------------------------------------------------------------------------------
UNION ALL SELECT 'Rod', 2011, 7, 10
)
SELECT
Name,
Year,
Year_Month,
SUM(sales) AS Total_Sales
FROM
MyTable
WHERE
(Year = DATEPART(YEAR, @DateParam) AND Year_Month <= DATEPART(MONTH, @DateParam))
OR (Year = DATEPART(YEAR, @DateParam) - 1 AND Year_Month > DATEPART(MONTH, @DateParam))
GROUP BY
Name,
Year,
Year_Month
注意:
1.这将给出截至2011年6月的12个月的结果
2. 2010年7月之前的数据不包括在内
3. Rod的数据差距不会导致注3违反
4. Jane在2011年5月和2011年6月缺失的数据不会导致注3违反
5. WHERE子句的公式将允许使用INDEX
答案 1 :(得分:2)
我无法从您的示例中了解year_month是如何存储的,这使得很难确定它是否适合以这种方式进行查询。
在这种情况下,我使用我所谓的相对月份,我计算为
(year - 2000) * 12 + (month -1)
因此,2000年1月是相对月0,2010年2月是相对月121等。
使用SQL Server标量函数可以轻松转换为年份和月份,使用&gt;,&lt;等等轻松查询
编辑:
刚刚看到你对year_month是什么以及你有一年的评论。用于计算year和year_month列的相对月值的标量函数对您有用。
然后你可以这样做:
where
dbo.GetRelativeMonth(year, year_month) >= @startRelativeMonth
and dbo.GetRelativeMonth(year, year_month) < @endRelativeMonth
虽然向表中添加relative_month列并在编写记录时计算值会更有效。
编辑2:
你问过GetRelativeMonth是如何工作的,所以这里是:
CREATE FUNCTION [dbo].[GetRelativeMonth]
(
@Year int,
@Month int
)
RETURNS int
AS
BEGIN
DECLARE @Result int
SELECT @Result = (@Year - 2000) * 12 + (@Month - 1)
RETURN @Result
END
答案 2 :(得分:1)
假设您使用的是SQL Server,您可以使用ROW_NUMBER函数来编制数据的子集,以便选择最终结果。
SELECT Name
, SUM(sales)
FROM (
SELECT rn = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Year, Year_Month)
, Name
, sales = SUM(sales)
FROM @Total_Sales ts
WHERE (YEAR(@Param) <= ts.Year AND MONTH(@Param) <= ts.Year_Month)
OR (YEAR(@Param) < ts.Year)
GROUP BY
Name
, Year
, Year_Month
) ts
WHERE rn <= 12
GROUP BY
Name
DECLARE @Param DATE = '05-01-2011'
DECLARE @Total_Sales TABLE (
Name VARCHAR(32)
, Sales INTEGER
, Year_Month INTEGER
, Year INTEGER
)
INSERT INTO @Total_Sales VALUES
('Malcolm X', 1, 1, 2011)
, ('Malcolm X', 1, 2, 2011)
, ('Malcolm X', 1, 3, 2011)
, ('Malcolm X', 1, 4, 2011)
, ('Malcolm X', 1, 5, 2011)
, ('Malcolm X', 1, 6, 2011)
, ('Malcolm X', 1, 7, 2011)
, ('Malcolm X', 1, 8, 2011)
, ('Malcolm X', 1, 9, 2011)
, ('Malcolm X', 1, 10, 2011)
, ('Malcolm X', 1, 11, 2011)
, ('Malcolm X', 1, 12, 2011)
, ('Malcolm X', 1, 1, 2012)
, ('Ben Hur', 1, 2, 2012)
答案 3 :(得分:0)
也许您可以使用BETWEEN功能?其中YourDate BETWEEN minValue和maxvalue
答案 4 :(得分:0)
SELECT Name,SUM(sales)as totalsales,year_month FROM Total_Sales WHERE year_month = DATEADD(MONTH,-12,'31 -March-2000')GROUP BY Name,year_month
尝试类似的东西