简体   繁体   English

BigQuery 中的逐年逐月比较和本月至今

[英]Year over Year by Month Comparison and Month to Date in BigQuery

Edit: @shawnt00 has the correct answer.编辑:@shawnt00 有正确答案。 Thank you very much!非常感谢!

I am having trouble accurately doing a year over year comparison by month but at any point during the month.我无法准确地按月进行逐年比较,但在本月的任何时候。 For example for August 2022 vs 2021, I want to compare August 1 - August 25, rather than full month of August 2021.例如,对于 2022 年 8 月与 2021 年,我想比较 8 月 1 日至 8 月 25 日,而不是 2021 年 8 月的整个月份。

I am also using a daily date field.我也在使用每日日期字段。

I want the final result to basically be:我希望最终结果基本上是:

Product_ID, Year, Month, PY_Sales, CY_Sales Product_ID、年、月、PY_Sales、CY_Sales

Edit: I have daily totals.编辑:我有每天的总数。 Some products do have not sales on certain days though:有些产品在某些日子没有销售:

product_id product_id sale_date发售日期 units单位
1 1 2021-01-01 2021-01-01 5 5
2 2 2021-01-02 2021-01-02 4 4
... ... ... ... ... ...
1 1 2021-06-05 2021-06-05 2 2
2 2 2022-01-06 2022-01-06 1 1
2 2 2022-08-15 2022-08-15 9 9

This is the code I have, but it doesn't do MTD.这是我拥有的代码,但它不执行 MTD。 So 2021 August is the entire month of August and I want it the same dates for 2022. I used this code because some products do not have sales on certain months.所以 2021 年 8 月是整个 8 月,我希望它与 2022 年的日期相同。我使用此代码是因为某些产品在某些月份没有销售。

    WITH cte AS 
(
SELECT 
     PRODUCT_ID,
     EXTRACT(YEAR FROM SALE_DATE) AS Year,
     EXTRACT(MONTH FROM SALE_DATE) AS Month,
     CONCAT(EXTRACT(YEAR FROM SALE_DATE), '-',EXTRACT(MONTH FROM SALE_DATE)) AS Year_Month,
     SUM(Units) AS Units
FROM data
WHERE Product_ID = 1
AND DATE(SALE_DATE) >= '2019-01-01'
GROUP BY 1, 2, 3
),

    diff AS 
( 
SELECT 
     COALESCE(c.PRODUCT_ID, p.PRODUCT_ID) AS Product_ID,
     COALESCE(c.Year, p.Year + 1) AS Year,
     COALESCE(c.Month, p.Month) AS Month,
     IFNULL(c.Units, 0) AS Current_Units,
     IFNULL(p.Units, 0) AS Previous_Units,
     NULLIF(((IFNULL(c.Units, 0) - IFNULL(p.Units,0)) / p.Units),0) * 100 AS Percent_Change
FROM CTE c
FULL OUTER JOIN CTE p ON c.PRODUCT_ID = p.PRODUCT_ID AND c.Year = p.Year + 1 AND c.Month = p.Month
WHERE c.Year <= EXTRACT(YEAR FROM CURRENT_DATE())
ORDER BY 2, c.Year, c.Month
)
SELECT *
FROM diff
--This is to avoid dividing by 0
WHERE diff.Previous_Units > 0
--AND Percent_Change <= -.5

You could just roll up two different monthly totals and then switch for the current month comparison:您可以汇总两个不同的每月总计,然后切换到当前月份的比较:

with agg as (
    select
        PRODUCT_ID,
        extract(year from SALE_DATE) as yr,
        extract(month from SALE_DATE) as mth,
        sum(Units) as Units,
        sum(case when extract(day from SALE_DATE) <= extract(day from current_date())
                 then Units end) as UnitsMTD
    from data
    where date(SALE_DATE) >= '2019-01-01' -- one year before report output
    group by 1, 2, 3
)
select c.Yr, c.Mth, c.PRODUCT_ID,
    case when Yr  = extract(year  from current_date())
          and Mth = extract(month from current_date())
         then (c.UnitsMTD - p.UnitsMTD) / p.UnitsMTD
         else (c.Units    - p.Units   ) / p.Units
    end as Percent_Change
from agg c left outer join agg p
    on p.Product_ID = c.Product_ID and p.Yr = c.Yr - 1 and p.Mth = c.Mth
order by c.Yr, c.Mth, c.PRODUCT_ID;

Note my earlier comment about leap years.请注意我之前关于闰年的评论。 This will treat February 28 of the year following a leap year as an "MTD" month.这会将闰年之后的次年 2 月 28 日视为“MTD”月份。 You might need to handle that differently inside the case expression.您可能需要在case表达式中以不同方式处理它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM