我知道SQL Server是STDEV和STDEVP的聚合函数。但是,在我的具体情况下,我的表缺少数据。表中显示了每小时的产品库存。当缺少一个小时时,这意味着库存为0.假设我想计算一整天2012-01-01产品“香蕉”数量的标准差,我该怎么做? / p>
谢谢!
数据
+---------------------+-------------+--------------+
| Date | ProductName | ProductCount |
+---------------------+-------------+--------------+
| 2012-01-01 00:00:00 | Banana | 15000 |
| 2012-01-01 01:00:00 | Banana | 16000 |
| 2012-01-01 02:00:00 | Banana | 17000 |
| 2012-01-01 05:00:00 | Banana | 12000 |
| 2012-01-01 00:00:00 | Apple | 5000 |
| 2012-01-01 05:00:00 | Apple | 6000 |
+---------------------+-------------+--------------+
SQL
CREATE TABLE ProductInventory (
[Date] DATETIME,
[ProductName] NVARCHAR(50),
[ProductCount] INT
)
INSERT INTO ProductInventory VALUES ('2012-01-01 00:00:00', 'Banana', 15000)
INSERT INTO ProductInventory VALUES ('2012-01-01 01:00:00', 'Banana', 16000)
INSERT INTO ProductInventory VALUES ('2012-01-01 02:00:00', 'Banana', 17000)
INSERT INTO ProductInventory VALUES ('2012-01-01 05:00:00', 'Banana', 12000)
INSERT INTO ProductInventory VALUES ('2012-01-01 00:00:00', 'Apple', 5000)
INSERT INTO ProductInventory VALUES ('2012-01-01 05:00:00', 'Apple', 6000)
答案 0 :(得分:2)
你可以使用CTE功能(我让你搜索它)来获得从1到24的小时。
但是创建一个“小时表”可能很容易,值为0到23。
假设你有一个带小时字段的小时表
select stdev(coalesce(pi.ProductCount, 0))
from hours h
left join ProductInventory pi on DATEPART(hh, pi.Date) = h.hour
where coalesce(pi.ProductName, 'Banana') = 'Banana'
and (pi.Date is null or (Convert(char(8), pi.Date, 112))='20120101')
答案 1 :(得分:1)
STDEV(isnull(ProductCount,0))
答案 2 :(得分:1)
为Products表构建一个小时表LEFT JOIN
:
DECLARE @h TABLE(hr DATETIME);
DECLARE @StartTime DATETIME='1/1/2012 00:00:00';
DECLARE @EndTime DATETIME='1/1/2012 23:00:00';
DECLARE @HourCount INT = DATEDIFF(HOUR,@StartTime,@EndTime)+1;
DECLARE @Product VARCHAR(30) = 'Banana';
INSERT INTO @h
SELECT TOP(@HourCount) DATEADD(HOUR,ROW_NUMBER()OVER(ORDER BY message_id)-1,@StartTime)
FROM sys.messages;
SELECT [ProductName]=ISNULL([ProductName],@Product)
, sd=STDEV(ISNULL([ProductCount],0))
FROM @h h
LEFT JOIN ProductInventory i ON h.hr = i.[Date]
WHERE ISNULL([ProductName],@Product)=@Product
GROUP BY ISNULL([ProductName],@Product);
结果:
ProductName sd
-------------------------------------------------- ----------------------
Banana 5763.45307123671
答案 3 :(得分:1)
生成0记录的成本相当高,尤其是在使用大量数据时。您还可以使用此查询来运行计算,而无需为缺失的零创建其他记录:
select #ProductInventory.ProductName,
sqrt((sum(Power((DataSum / TotalDataPoints - ProductCount), 2)) + ZeroDataPoints * power(DataSum / TotalDataPoints, 2))/(TotalDataPoints-1)) stdDev,
sqrt((sum(Power((DataSum / TotalDataPoints - ProductCount), 2)) + ZeroDataPoints * power(DataSum / TotalDataPoints, 2))/(TotalDataPoints)) stdDevP
from #ProductInventory
join
(
select ProductName,
convert(float,SUM(ProductCount)) DataSum,
convert(float,datediff(hour, min(Date), MAX(date)) + 1) TotalDataPoints,
convert(float,datediff(hour, min(Date), MAX(date)) + 1 - COUNT(ProductCount)) ZeroDataPoints
from #ProductInventory
group by ProductName
) Aggregates
on #ProductInventory.ProductName = Aggregates.ProductName
Group by #ProductInventory.ProductName, DataSum, TotalDataPoints, ZeroDataPoints
这假设您的第一个和最后一个数据点在集合中。因此,如果您想要使用整个24小时工作日,则必须确保第一个和最后一个值(如果不存在)的集合中至少添加了0个数据点。例如,在这种情况下,您可以在运行上述查询之前使用此代码添加日终点:
INSERT INTO #ProductInventory VALUES ('2012-01-01 23:00:00', 'Banana', 0)
INSERT INTO #ProductInventory VALUES ('2012-01-01 23:00:00', 'Apple', 0)