SQL 查询以获取过去 17 周内按周分组的数据
SQL query to get the data grouped by weeks for the last 17 weeks
我们正尝试在 SQL Server 2012 中按周分组过去 17 周。
输入数据
OrderDate OrderValue
----------------------
7/17/11 10
7/24/11 20
7/31/11 30
8/7/11 40
SQL试了一下:不知道方向是否正确
Select
om.OrderDate, SUM(MOrderQty * MPrice) as OrderValue
from
OrdMaster om
inner join
OrdDetail od on om.SalesOrder = od.SalesOrder
where
om.OrderDate >= DATEADD(WEEK, -17,getdate())
group by
om.OrderDate
输出数据:
OrderValue 7/17/11 7/24/11 7/31/11 8/7/11 8/14/11 8/21/11 8/28/11 9/4/11 9/11/11 9/18/11 9/25/11 10/2/11 10/9/11 10/16/11 10/23/11 10/30/11 11/6/11
如有任何帮助,我们将不胜感激!提前致谢!
尝试:
Select datepart(week, om.OrderDate)),
SUM(MOrderQty * MPrice) as OrderValue
from OrdMaster om
inner join OrdDetail od
on om.SalesOrder = od.SalesOrder
where om.OrderDate >= DATEADD(WEEK, -17,getdate())
group by datepart(week, om.OrderDate))
参见here。
首先,我建议,如果您在这两个表上还没有以下索引,请考虑添加它们以支持我们准备做的事情以及更多。
--===== If you don't already have them, consider adding these indexes
CREATE NONCLUSTERED INDEX By_OrderDate
ON [dbo].OrdMaster([OrderDate])
INCLUDE ([SalesOrder])
;
CREATE NONCLUSTERED INDEX By_SalesOrder
ON dbo.OrdDetail([SalesOrder])
INCLUDE ([MOrderQty],[MPrice])
;
要做到这一切 "auto-magical",我们必须使用一些动态 SQL。它称为 "Pre-Aggregated Dynamic CROSSTAB",它比大多数 PIVOT 运算符都快。它将使您不必每周都接触代码,而且速度非常快。我还冒昧地添加了一个 "Total" 列。详情在代码中。
我也使用 "tokenized" 动态 SQL 只是为了使代码更容易。它不一定是 SQL 注入证明(必须经常使用 QUOTENAME),但由于数据类型正在转换,这里不可能这样做。
而且,是的,这为您提供了您正在寻找的 "horizontal format"。
--=======================================================================================
-- Builds and executes a high performance, pre-aggregated CROSS TAB that will
-- return the previous 17 weeks without having to adjust the code no matter
-- what today's date is. It also returns a total for the 17 weeks.
--
-- Note that if any give week has no sales, then you'll have bigger things to
-- worry about other than this code won't pick up that missing week. ;-)
-- We could fix that but it's not worth it because it shouldn't ever happen.
--=======================================================================================
--===== If the pre-aggregate table already exists, drop it to make reruns in SSMS easier.
IF OBJECT_ID('tempdb..#PreAgg','U') IS NOT NULL
DROP TABLE #PreAgg
;
--===== Pre-aggregate the data into a working table.
-- The right indexes will make this very fast and it greatly reduces the amount of
-- work the CROSSTAB will have to do.
SELECT WeekDate = CAST(DATEADD(dd,DATEDIFF(dd,-1,om.OrderDate)/7*7,-1) AS DATE)
,OrderValue = SUM(od.MOrderQty * od.MPrice)
INTO #PreAgg
FROM dbo.OrdMaster om
JOIN dbo.OrdDetail od ON om.SalesOrder = od.SalesOrder
WHERE om.OrderDate >= DATEADD(WK,-17,DATEADD(dd,DATEDIFF(dd,-1,GETDATE())/7*7,-1))
AND om.OrderDate < DATEADD(dd,DATEDIFF(dd,-1,GETDATE())/7*7,-1)
GROUP BY DATEDIFF(dd,-1,om.OrderDate)/7*7
;
--===== Declare a place to build the dynamic SQL in.
DECLARE @SQL VARCHAR(8000)
;
--===== Create the dynamic SELECT list of the CROSSTAB from the preggregated table.
SELECT @SQL = ISNULL(@SQL+SPACE(8)+',','')
+ REPLACE(REPLACE(
'[<<WeekDate>>] = SUM(CASE WHEN WeekDate = "<<WeekDate>>" THEN OrderValue ELSE 0 END)
' ,'"' ,'''') --These are the other end of the replaces.
,'<<WeekDate>>',CONVERT(CHAR(8),WeekDate,1))
FROM #PreAgg
ORDER BY WeekDate
;
--===== Create the static parts of the dynamic CROSSTAB SQL and insert the dynamic part.
SELECT @SQL = REPLACE('
SELECT <<@SQL>> ,[Total] = SUM(OrderValue)
FROM #Preagg
;' ,'<<@SQL>>',@SQL) --The other end of the replace
;
--===== Display the dynamic SQL for troubleshooting purposes.
-- This can be commented out for production.
PRINT @SQL
;
--===== Execute the dynamic SQL
EXEC (@SQL)
;
我们正尝试在 SQL Server 2012 中按周分组过去 17 周。
输入数据
OrderDate OrderValue
----------------------
7/17/11 10
7/24/11 20
7/31/11 30
8/7/11 40
SQL试了一下:不知道方向是否正确
Select
om.OrderDate, SUM(MOrderQty * MPrice) as OrderValue
from
OrdMaster om
inner join
OrdDetail od on om.SalesOrder = od.SalesOrder
where
om.OrderDate >= DATEADD(WEEK, -17,getdate())
group by
om.OrderDate
输出数据:
OrderValue 7/17/11 7/24/11 7/31/11 8/7/11 8/14/11 8/21/11 8/28/11 9/4/11 9/11/11 9/18/11 9/25/11 10/2/11 10/9/11 10/16/11 10/23/11 10/30/11 11/6/11
如有任何帮助,我们将不胜感激!提前致谢!
尝试:
Select datepart(week, om.OrderDate)),
SUM(MOrderQty * MPrice) as OrderValue
from OrdMaster om
inner join OrdDetail od
on om.SalesOrder = od.SalesOrder
where om.OrderDate >= DATEADD(WEEK, -17,getdate())
group by datepart(week, om.OrderDate))
参见here。
首先,我建议,如果您在这两个表上还没有以下索引,请考虑添加它们以支持我们准备做的事情以及更多。
--===== If you don't already have them, consider adding these indexes
CREATE NONCLUSTERED INDEX By_OrderDate
ON [dbo].OrdMaster([OrderDate])
INCLUDE ([SalesOrder])
;
CREATE NONCLUSTERED INDEX By_SalesOrder
ON dbo.OrdDetail([SalesOrder])
INCLUDE ([MOrderQty],[MPrice])
;
要做到这一切 "auto-magical",我们必须使用一些动态 SQL。它称为 "Pre-Aggregated Dynamic CROSSTAB",它比大多数 PIVOT 运算符都快。它将使您不必每周都接触代码,而且速度非常快。我还冒昧地添加了一个 "Total" 列。详情在代码中。
我也使用 "tokenized" 动态 SQL 只是为了使代码更容易。它不一定是 SQL 注入证明(必须经常使用 QUOTENAME),但由于数据类型正在转换,这里不可能这样做。
而且,是的,这为您提供了您正在寻找的 "horizontal format"。
--=======================================================================================
-- Builds and executes a high performance, pre-aggregated CROSS TAB that will
-- return the previous 17 weeks without having to adjust the code no matter
-- what today's date is. It also returns a total for the 17 weeks.
--
-- Note that if any give week has no sales, then you'll have bigger things to
-- worry about other than this code won't pick up that missing week. ;-)
-- We could fix that but it's not worth it because it shouldn't ever happen.
--=======================================================================================
--===== If the pre-aggregate table already exists, drop it to make reruns in SSMS easier.
IF OBJECT_ID('tempdb..#PreAgg','U') IS NOT NULL
DROP TABLE #PreAgg
;
--===== Pre-aggregate the data into a working table.
-- The right indexes will make this very fast and it greatly reduces the amount of
-- work the CROSSTAB will have to do.
SELECT WeekDate = CAST(DATEADD(dd,DATEDIFF(dd,-1,om.OrderDate)/7*7,-1) AS DATE)
,OrderValue = SUM(od.MOrderQty * od.MPrice)
INTO #PreAgg
FROM dbo.OrdMaster om
JOIN dbo.OrdDetail od ON om.SalesOrder = od.SalesOrder
WHERE om.OrderDate >= DATEADD(WK,-17,DATEADD(dd,DATEDIFF(dd,-1,GETDATE())/7*7,-1))
AND om.OrderDate < DATEADD(dd,DATEDIFF(dd,-1,GETDATE())/7*7,-1)
GROUP BY DATEDIFF(dd,-1,om.OrderDate)/7*7
;
--===== Declare a place to build the dynamic SQL in.
DECLARE @SQL VARCHAR(8000)
;
--===== Create the dynamic SELECT list of the CROSSTAB from the preggregated table.
SELECT @SQL = ISNULL(@SQL+SPACE(8)+',','')
+ REPLACE(REPLACE(
'[<<WeekDate>>] = SUM(CASE WHEN WeekDate = "<<WeekDate>>" THEN OrderValue ELSE 0 END)
' ,'"' ,'''') --These are the other end of the replaces.
,'<<WeekDate>>',CONVERT(CHAR(8),WeekDate,1))
FROM #PreAgg
ORDER BY WeekDate
;
--===== Create the static parts of the dynamic CROSSTAB SQL and insert the dynamic part.
SELECT @SQL = REPLACE('
SELECT <<@SQL>> ,[Total] = SUM(OrderValue)
FROM #Preagg
;' ,'<<@SQL>>',@SQL) --The other end of the replace
;
--===== Display the dynamic SQL for troubleshooting purposes.
-- This can be commented out for production.
PRINT @SQL
;
--===== Execute the dynamic SQL
EXEC (@SQL)
;