我正在尝试创建一个函数,该函数接收一个句点的开始日期和日期结束作为参数,并生成一个列表,其中列出了该期间每个月销售的前5个产品。
例如:
CREATE FUNCTION top5Sales(@CurrentDate DATETIME, @EndDate DATETIME)
RETURNS TABLE
RETURN
(
WHILE(@CurrentDate < @EndDate)
BEGIN
SELECT TOP 5
AdventureWorks.Sales.SalesOrderDetail.ProductID,
AdventureWorks.Production.Product.Name,
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate) as 'Month',
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate) as 'Year',
SUM(AdventureWorks.Sales.SalesOrderDetail.OrderQty) as 'Total Quantity Sold',
AVG(AdventureWorks.Sales.SalesOrderDetail.UnitPrice) as 'Average Unit Price',
SUM(AdventureWorks.Sales.SalesOrderDetail.UnitPriceDiscount) as 'Total Discount',
SUM(AdventureWorks.Sales.SalesOrderDetail.LineTotal) as 'Total Value Sold'
FROM
AdventureWorks.Sales.SalesOrderDetail
INNER JOIN
AdventureWorks.Sales.SalesOrderHeader
ON
AdventureWorks.Sales.SalesOrderHeader.SalesOrderID = AdventureWorks.Sales.SalesOrderDetail.SalesOrderID
INNER JOIN
AdventureWorks.Production.Product
ON
AdventureWorks.Production.Product.ProductID = AdventureWorks.Sales.SalesOrderDetail.ProductID
WHERE
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate) = month(@CurrentDate)
and
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate) = year(@CurrentDate)
GROUP BY
AdventureWorks.Production.Product.Name,
AdventureWorks.Sales.SalesOrderDetail.ProductID,
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate),
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate)
ORDER BY
[Total Quantity Sold] DESC
SET
@CurrentDate = DATEADD(MONTH, 1, @CurrentDate)
END
)
实际上,上面的代码是错误的。它仅用于举例说明问题,并提供一些可能的解决方案。
您不必遵循这一思路。如果还有另一个更有趣的解决方案,请随意公开它。
答案 0 :(得分:0)
您可以使用row_number和前5个关系,并使用单个查询返回此结果,如下所示:您能检查一下吗?
CREATE FUNCTION top5Sales(@CurrentDate DATETIME, @EndDate DATETIME)
RETURNS TABLE
RETURN
(
SELECT Top 5 with ties * from (
SELECT
AdventureWorks.Sales.SalesOrderDetail.ProductID,
AdventureWorks.Production.Product.Name,
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate) as 'Month',
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate) as 'Year',
SUM(AdventureWorks.Sales.SalesOrderDetail.OrderQty) as 'Total Quantity Sold',
AVG(AdventureWorks.Sales.SalesOrderDetail.UnitPrice) as 'Average Unit Price',
SUM(AdventureWorks.Sales.SalesOrderDetail.UnitPriceDiscount) as 'Total Discount',
SUM(AdventureWorks.Sales.SalesOrderDetail.LineTotal) as 'Total Value Sold'
FROM
AdventureWorks.Sales.SalesOrderDetail
INNER JOIN
AdventureWorks.Sales.SalesOrderHeader
ON
AdventureWorks.Sales.SalesOrderHeader.SalesOrderID = AdventureWorks.Sales.SalesOrderDetail.SalesOrderID
INNER JOIN
AdventureWorks.Production.Product
ON
AdventureWorks.Production.Product.ProductID = AdventureWorks.Sales.SalesOrderDetail.ProductID
WHERE
AdventureWorks.Sales.SalesOrderHeader.OrderDate > @CurrentDate
AND AdventureWorks.Sales.SalesOrderHeader.OrderDate <= @EndDate
GROUP BY
AdventureWorks.Production.Product.Name,
AdventureWorks.Sales.SalesOrderDetail.ProductID,
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate),
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate)
-- ORDER BY
-- [Total Quantity Sold] DESC
) a
Order by Row_Number() over(Partition by [ProductId], [Name], [Year], [Month] order by [Total Quantity Sold] Desc
)
答案 1 :(得分:-1)
我查看了AdventureWorks数据库,但我没有看到日期表。有关基本概述,您可以查看此视频 - https://www.brentozar.com/training/t-sql-level/3-number-date-tables-10m/
以下逻辑不会出现在内联表函数中,但它是一种选择您正在寻找的数据的快速而简单的方法。
DECLARE @sql NVARCHAR(Max),
@CurrentDate DATETIME = '2005-06-01 00:00:00.000',
@EndDate DATETIME = '2008-08-31 00:00:00.000';
SELECT @sql = COALESCE( @sql + CHAR(13) + 'UNION' + CHAR(13), '') +
' SELECT TOP 5 ' + CONVERT(NVARCHAR(8), [Year]) + ' AS [Year], '
+ CONVERT(NVARCHAR(8), [Month]) + ' AS [Month],
sod.ProductId,
SUM(sod.OrderQty) AS Sales
FROM Sales.SalesOrderDetail sod
JOIN Sales.SalesOrderHeader soh
ON sod.SalesOrderId = soh.SalesOrderId
AND YEAR(soh.OrderDate) = ' + CONVERT(NVARCHAR(8), [Year]) + '
AND MONTH(soh.OrderDate) = ' + CONVERT(NVARCHAR(8), [Month]) + '
GROUP BY sod.ProductId'
FROM dbo.[Date]
WHERE [Date] BETWEEN @CurrentDate AND @EndDate
EXEC sp_executesql @sql
如果您执行此T-SQL,您会发现它相对于获取相同数据的其他方法而言非常快且可扩展。