Home > Software design >  How to round date to closest month?
How to round date to closest month?

Time:10-13

I need to round dates to the closest month start. For example, I would like 2022-08-30 and 2022-09-03 to both evaluate to 2022-09-01.

How can I do this with Snowflake SQL?

CodePudding user response:

We can encapsulate this logic into a SQL UDF:

create or replace function round_to_month(d date)
returns date
as $$
select x 
from (
    select date_trunc(month, d) before
        , dateadd(month, 1, before) after      
        , iff(d-before < after-d, before, after) x
)
$$

Sample:


with data(d) as (
    select $1::date
    from values('2020-01-10'), ('2020-01-20'), ('2020-01-16'), ('2020-01-17')
)

select *, round_to_month(d)
from data

CodePudding user response:

Approach 1: Adding 1 month to beginning of month if day of date is greater than midpoint:

WITH cte(d) AS (
    SELECT s.d::DATE
    FROM VALUES('2020-01-10'), ('2020-01-20'), ('2020-01-16'), 
               ('2020-01-17'), ('2022-02-14') AS s(d)
)
SELECT d
      ,DATEADD('MONTH'
               ,(DAY(d) > CEIL(DAY(LAST_DAY(d)))/2)::INT
               ,DATE_TRUNC('MONTH', d)
              ) AS round_to_month
FROM cte;

Output:

D ROUND_TO_MONTH
2020-01-10 2020-01-01
2020-01-20 2020-02-01
2020-01-16 2020-02-01
2020-01-17 2020-02-01
2022-02-14 2022-02-01

Approach 2:

Snowflake provides TIME_SLICE function which is the easiest way to get start of current/next month:

SELECT '2022-10-13'::DATE AS d
      ,TIME_SLICE(d, 1, 'MONTH', 'START') AS prev
      ,TIME_SLICE(d, 1, 'MONTH', 'END') AS next

Output:

D PREV NEXT
2022-10-13 2022-10-01 2022-11-01

Using the same idea as Felipe's answer:

WITH cte(d) AS (
    SELECT s.d::DATE
    FROM VALUES('2020-01-10'), ('2020-01-20'), ('2020-01-16'),
               ('2020-01-17'), ('2022-02-14') AS s(d)
)
SELECT d,
  CASE WHEN d-TIME_SLICE(d, 1, 'MONTH', 'START') < TIME_SLICE(d, 1, 'MONTH', 'END')-d
       THEN TIME_SLICE(d, 1, 'MONTH', 'START')
       ELSE TIME_SLICE(d, 1, 'MONTH', 'END')
  END AS rount_to_month
FROM cte;
  • Related