计算用零替换缺失行的预定义值的平均值和标准偏差

uwopmtnx  于 2021-07-24  发布在  Java
关注(0)|答案(3)|浏览(264)

我有一个简单的表,其中包含一年中产品及其每天总销售额的记录(只有3列-产品、日期、销售额)。所以,举个例子,如果产品a每天都有销售,它就有 365 记录。同样地,如果产品b只卖50天,那么这个表就只有 50 该产品的行-每销售一天一行。
我需要计算全年的日均销售额和标准差,这意味着,对于产品b,我需要额外的 365-50=315 销售为零的分录能够正确计算年度的日平均值和标准差。
有没有一种方法可以在sql中高效、动态地实现这一点?
谢谢

s3fp2yjn

s3fp2yjn1#

我们可以生成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);

您可以用例如。 AVG(COALESCE(numsales, 0)) . 您可能还需要一个where子句来消除非闰年的366天(例如将年份除以4,如果是0,则只执行366行)。
如果你只做了一年,你可以在sales子查询中使用where子句只给出相关的记录;最有效的方法是使用 WHERE salesdate >= DATEFROMPARTS(YEAR(GetDate()), 1, 1) AND salesdate < DATEFROMPARTS(YEAR(GetDate()) + 1, 1, 1) 而不是在每个销售日期调用函数,从中提取年份以与常量进行比较。如果只有一年,您还可以从select/group by中删除年份(salesdate)
如果你做了很多年,你可以让rg生成更多的行,或者(也许更简单)交叉连接到一个年份列表,这样你就得到366行乘以例如。 VALUES (2015),(2016),(2017),(2018),(2019),(2020) (并从销售部分加入年份)

mwngjboj

mwngjboj2#

找到一年中的第一天和最后一天,然后使用 datediff() 找到当年的天数。
在那之后不要使用 AVG 关于销售,但是 SUM(Sales) / days_in_year ```
select *,
days_in_year = datediff(day, first_of_year, last_of_year) + 1
from (values (2019), (2020)) v(year)
cross apply
(
select first_of_year = dateadd(year, year - 1900, 0),
last_of_year = dateadd(year, year - 1900 + 1, -1)
) d

3duebb1j

3duebb1j3#

有一个不同的方法来看待它-不要试图添加额外的空行,只是除以一年中的天数。虽然一年的天数不是恒定的(闰年有366天),但由于一年的第一天总是1月1日,最后一天总是12月31日,因此可以很容易地计算:

SELECT   YEAR(date), 
         product,
         SUM(sales) / DATEPART(dy, DATEFROMPARTS(YEAR(date)), 12, 31))
FROM     sales_table
GROUP BY YEAR(date), product

相关问题