我正在构建一个存储过程,从多个不同的表中提取大量不同的数据,我需要一种方法从销售表中提取销售信息,然后对该销售数据执行各种汇总。在下面的示例中,我使用临时表来完成此操作,但有人建议可能有更好的方法。有没有更有效的方法来完成我在这里做的事情?
SELECT * INTO #TempSales FROM [Sales] WHERE ClientId = @ClientId
SELECT
[Customer].[CustomerID],
[Customer].[AccountBalAmountOpen],
[Customer].[AccountAgeAmountDays0],
[Customer].[AccountAgeAmountDays30],
[Customer].[AccountAgeAmountDays60],
[Customer].[AccountAgeAmountDays90],
[Customer].[AccountAgeAmountDaysOver90],
(SELECT SUM(SalesAmount) FROM #TempSales WHERE CustomerId = [Customer].[CustomerID] AND Origin = 385) AS ServiceLifeTimeSales,
(SELECT SUM(SalesAmount) FROM #TempSales WHERE CustomerId = [Customer].[CustomerID] AND Origin = 385 AND MONTH(SaleDate) = MONTH(GETDATE()) AND YEAR(SaleDate) = YEAR(GETDATE())) AS ServiceMonthToDateSales,
(SELECT SUM(SalesAmount) FROM #TempSales WHERE CustomerId = [Customer].[CustomerID] AND Origin = 385 AND YEAR(SaleDate) = YEAR(GETDATE())) AS ServiceYearToDateSales,
(SELECT SUM(SalesAmount) FROM #TempSales WHERE CustomerId = [Customer].[CustomerID] AND Origin = 385 AND YEAR(SaleDate) = (YEAR(GETDATE()) - 1)) AS ServicePreviousYearSales,
(SELECT SUM(SalesAmount) FROM #TempSales WHERE CustomerId = [Customer].[CustomerID] AND Origin = 460) AS PartsLifeTimeSales,
(SELECT SUM(SalesAmount) FROM #TempSales WHERE CustomerId = [Customer].[CustomerID] AND Origin = 460 AND MONTH(SaleDate) = MONTH(GETDATE()) AND YEAR(SaleDate) = YEAR(GETDATE())) AS PartsMonthToDateSales,
(SELECT SUM(SalesAmount) FROM #TempSales WHERE CustomerId = [Customer].[CustomerID] AND Origin = 460 AND YEAR(SaleDate) = YEAR(GETDATE())) AS PartsYearToDateSales,
(SELECT SUM(SalesAmount) FROM #TempSales WHERE CustomerId = [Customer].[CustomerID] AND Origin = 460 AND YEAR(SaleDate) = (YEAR(GETDATE()) - 1)) AS PartsPreviousYearSales,
[Orders].[CustomerId] AS ParentCustomerId,
[Orders].[OrderId],
[Orders].[OrderStatus],
[Orders].[UnitId],
[Orders].[FleetId],
[Orders].[CreatedDate] AS OrderCreatedDate,
[Orders].[OrderType],
[OrderParts].[OrderId] AS ParentOrderId,
[OrderParts].[PartId],
[OrderParts].[PartDescription],
[OrderParts].[QuantityShip],
[OrderParts].[QuantityBackOrder],
[OrderParts].[CreatedDate] AS PartCreatedDate
FROM [Customer]
LEFT JOIN [Orders]
ON [Orders].[CustomerId] = [Customer].[CustomerID]
LEFT JOIN [OrderParts]
ON [OrderParts].[OrderId] = [Orders].[OrderId]
WHERE [Customer].[ClientID] = @ClientId
DROP TABLE #TempSales
答案 0 :(得分:0)
虽然临时表可用于存储将在其他查询中重用的复杂查询的中间结果,但我并不认为您在计算时需要它,因为您正在创建临时表:
SELECT * INTO #TempSales FROM [Sales] WHERE ClientId = @ClientId
您没有加入任何内容,也没有进行计算或使用聚合函数,因此如果表格已正确编入索引(至少ClientId
,CustomerId
,Origin
和{{1 }},您的查询应该执行得很好甚至更快,因为使用SalesDate
创建的表除了您手动添加之外没有任何索引。
但是你可能正在使用临时表来提高速度,因为你有这样的条件:
SELECT INTO
当您将过滤器列包含在函数中时make the query non-sargable。因此,查询优化器无法正确使用AND YEAR(SaleDate) = YEAR(GETDATE())
AND MONTH(SaleDate) = MONTH(GETDATE()) AND YEAR(SaleDate) = YEAR(GETDATE())
上的任何现有索引,并且由于时态表的行数较少,因此执行完全扫描所需的时间少于SaleDate
表
您可以使用不对过滤器列应用任何函数的条件来修复它(尽管您可以对常量值使用函数):
Sales
或者如果您使用的是早于SQL Server 2012的SQL版本:
declare @thisYearStart as datetime, @nextYearStart as datetime,
@thisMonthStart as datetime, @nextMonthStart as datetime
set @thisYearStart=DATEFROMPARTS(YEAR(GETDATE()),1,1)
set @nextYearStart=DATEADD(year,1,@thisYearStart)
set @thisMonthStart=DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()),1)
set @nextMonthStart=DATEADD(month,1,@thisMonthStart)
然后只使用:
set @thisYearStart=CAST(CAST(YEAR(GETDATE()) as char(4))+'0101' AS datetime) -- ISO format
set @nextYearStart=DATEADD(year,1,@thisYearStart)
set @thisMonthStart=DATEADD(month,MONTH(GETDATE())-1,@thisYearStart)
set @nextMonthStart=DATEADD(month,1,@thisMonthStart)
请注意,您不需要使用变量,您可以直接在AND SaleDate>=@thisYearStart AND SaleDate<@nextYearStart
AND SaleDate>=@thisMonthStart AND SaleDate<@nextMonthStart
条件下使用DATEFROMPARTS(...)
,但由于您已经使用它们创建了存储过程,因此他们将使用查询更具可读性。