sql - 计算用零替换缺失行的预定义值的平均值和标准偏差
问题描述
我有一个简单的表格,其中包含产品记录及其一年中每天的总销售额(只有 3 列 - 产品、日期、销售额)。因此,例如,如果产品 A 每天都售出,它就会有365
记录。同样,如果产品 B 仅售出 50 天,则该表将仅50
包含该产品的行 - 每一天销售一个。
我需要计算全年的日均销售额和标准差,这意味着,对于产品 B,我需要有额外365-50=315
的零销售额条目才能正确计算该年度的日均和标准差。
有没有办法在 SQL 中有效且动态地执行此操作?
谢谢
解决方案
我们可以生成 366 行并将销售数据加入其中:
WITH rg(rn) AS (
SELECT 1 AS rn
UNION ALL
SELECT a.rn + 1 AS rn
FROM rg a
WHERE a.rn <= 366
)
SELECT
*
FROM
rg
LEFT JOIN (
SELECT YEAR(saledate) as yr, DATEPART(dayofyear, saledate) as doy, count(*) as numsales
FROM sales
GROUP BY YEAR(saledate), DATEPART(dayofyear, saledate)
) s ON rg.rn = s.doy
OPTION (MAXRECURSION 370);
您可以用 eg 替换空值(当天没有销售数据)AVG(COALESCE(numsales, 0))
。您可能还需要一个 WHERE 子句来消除非闰年的第 366 天(例如 MODULO 将年份乘以 4,如果为 0,则仅执行 366 行)。
如果你只做一年,你可以在 sales 子查询中使用 where 子句来只给出相关记录;最有效的是使用范围 likeWHERE salesdate >= DATEFROMPARTS(YEAR(GetDate()), 1, 1) AND salesdate < DATEFROMPARTS(YEAR(GetDate()) + 1, 1, 1)
而不是在每个销售日期调用函数来从中提取年份以与常数进行比较。如果只有一年,您也可以从选择/分组中删除 YEAR(salesdate)
如果你做了很多年,你可以让 rg 生成更多的行,或者(也许更简单)将它交叉连接到一个年份列表中,这样你就可以得到 366 行乘以 eg VALUES (2015),(2016),(2017),(2018),(2019),(2020)
(并将年份从连接的销售部分也)
推荐阅读
- elixir - 如何使用 Elixir/Nerves 获取当前设备 IP
- python - 将日期时间转换为序数
- javascript - hls.js hls.subtitleTracks 返回空数组
- image - 未能呈现 B64 编码的 Thymeleaf
- regex - 正则表达式 - 在字符的出现数 N 后开始匹配
- flutter - Flutter/Dart 使用 ListView.builder 为每个 x 项目构建一个不同的小部件
- sql - 根据前一行和相同的计算列计算列值
- java - 使用日期错误打印月份中的日期?
- c++ - 如何创建派生对象的向量?
- azure - Ansible 查找特定键