r' s peiling_date等效于sql

发布于 2025-01-26 14:52:54 字数 457 浏览 1 评论 0原文

我想在SQL(PostgreSQL)中实现R的ceiling_date fucntion。

因此,我每天都有一个日期,每天都有相应的销售,我想在一个日期(例如星期五)积累一个星期的销售。

输入格式:

“输入格式”
汇总销售的日期

黄色的日期是按预期输出格式

任何帮助将不胜感激。谢谢

I want to implement R's ceiling_date fucntion in SQL (Postgresql).

So I have dates in a column for everyday with corresponding sales and I want to accumulate the sales for a week over a single date (say Friday).

Input Format:

Input format
Dates in yellow are the dates to aggregate sales on

Expected output format:

Expected Output format

This can easily be done in R using ceiling_date but I want to do it in SQL itself.

Any help would be appreciated. Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

错々过的事 2025-02-02 14:52:54

接受和处理 iso 8601 标准是处理日期范围的最简单的标准。但是,这实质上是一个标准定义,这本质上是:

  1. 所有周都恰好为7天。
  2. 整个星期从星期一开始。
  3. 一年中的第一周是包含4日的一周。

date_trunc 功能一周中的一天。

-- ISO 8601 Week definition 
select (date_trunc('week',dte)::date +6)  "Week Ending"
     , sum(sales)                         "Total Sales"
  from test    
  group by (date_trunc('week',dte)::date +6)
  order by (date_trunc('week',dte)::date +6);

非ISO 8601的日期/周处理提出了一些棘手的过程,以获取适当的周定义。以下是星期五至周四的一周定义。它创建a 日期范围从桌子上的第一个星期五开始的一年,然后使用该范围包含操作员加入以确定适当的求和期,

with periods (wk) as 
     ( select daterange( ((min_dt + (n-1) * interval '1 week'))::date     
                       , ((min_dt + (n)   * interval '1 week'))::date 
                       , '(]'
                       ) 
        from (select min(dte) min_dt 
                from test
               where extract(dow from dte) = 5     --- Day_Of_Week (5) = Friday
             ) s
        cross join generate_series(0,52) gs(n) 
     ) --select * from periods;
select upper(wk)-1   "Week Ending" 
    ,  sum(sales)    "Total Sales"
  from periods
  join test 
    on (dte <@ wk)
group by upper(wk)-1 
order by upper(wk)-1;

请参见两个
注意:演示更改样本日期,从1月(2022-01-01 ...)到5月(2022-05-01 ...),因为2022年1月6日是星期四,星期五不是描述,但20122年6月6日是5月6日。星期五。同样,结束6-MAY的值的总和为38(不是42个)。最后,都没有查询尝试限制日期,但是通过数据结束进行处理。要么可以解决多年的数据。

Accepting and processing the ISO 8601 Standard is by far the easiest for processing date ranges. But this imposes a standard definition, which is essentially:

  1. All weeks consist on exactly 7 days.
  2. All weeks begin on Monday.
  3. The first week of the year is the week the contains 4-Jan.

The date_trunc function gives the first date of the week, adding 6 gives the last day of the week.

-- ISO 8601 Week definition 
select (date_trunc('week',dte)::date +6)  "Week Ending"
     , sum(sales)                         "Total Sales"
  from test    
  group by (date_trunc('week',dte)::date +6)
  order by (date_trunc('week',dte)::date +6);

Date/Week processing for non ISO 8601 presents somewhat tricky process to get the appropriate week definition. The following does so for week Friday - Thursday definition. It creates a date range for a year beginning with the first Friday in the table, then joins using the range contains operator to determine the appropriate summation period

with periods (wk) as 
     ( select daterange( ((min_dt + (n-1) * interval '1 week'))::date     
                       , ((min_dt + (n)   * interval '1 week'))::date 
                       , '(]'
                       ) 
        from (select min(dte) min_dt 
                from test
               where extract(dow from dte) = 5     --- Day_Of_Week (5) = Friday
             ) s
        cross join generate_series(0,52) gs(n) 
     ) --select * from periods;
select upper(wk)-1   "Week Ending" 
    ,  sum(sales)    "Total Sales"
  from periods
  join test 
    on (dte <@ wk)
group by upper(wk)-1 
order by upper(wk)-1;

See demo of both here.
NOTE: Demo changes sample date from January (2022-01-01 ...) to May (2022-05-01 ...) as 6-January-2022 was Thursday not Friday as description, 6-May-2022 is however Friday. Also the sum of values ending 6-May is 38 (not 42 as indicated). Finally, neither query attempts a limiting date, but processed through end-of-data. Nor does either address multiple years of data.

蝶舞 2025-02-02 14:52:54

” 2022-大1月20日,有3个星期五:'2022-01-07','2022-01-14','2022-01-21'。
我们需要按照这3个星期五的订单按销售日期进行分区。
现在,问题是要计算所有这些日期属于这3个星期五。

  • 每个星期五每个sales_date属于。
  • 处理特殊案例(星期五之后一个星期:星期六,星期日),当时sales_date&gt;星期五,真实的星期五是下周五。

最终代码:

SELECT
    *,
    sum(amount) OVER (PARTITION BY sales.compute_friday ORDER BY sales_date)
FROM
    sales;

处理代码:

BEGIN;
CREATE TABLE sales (
    sales_date date
    , amount numeric
);
INSERT INTO sales (sales_date , amount)
SELECT
    i
    , (random() * 10)::integer
FROM
    generate_series('2022-01-01'::timestamp , '2022-01-20'::timestamp , interval '1 day') g (i);
ALTER TABLE sales
    ADD COLUMN friday date;
UPDATE
    sales
SET
    friday = (date_trunc('week' , sales_date) + interval '4 day')::date;
ALTER TABLE sales
    ADD COLUMN compute_friday date;
UPDATE
    sales
SET
    compute_friday = CASE WHEN sales_date > friday THEN
        (friday + interval '7 days')::date
    ELSE
        friday
    END;
COMMIT;

demo

idea: for 2022-Janurary-1 to 2022-Janurary-20, there is 3 Fridays:'2022-01-07','2022-01-14', '2022-01-21'.
We need to partition by these 3 friday order by sales date.
Now the problem is now to compute get all these date belong to these 3 fridays.

  • get every friday each sales_date belong to.
  • deal with special cases(one week after friday: saturday, sunday) when sales_date > friday then the real friday is next friday.

final code:

SELECT
    *,
    sum(amount) OVER (PARTITION BY sales.compute_friday ORDER BY sales_date)
FROM
    sales;

processing code:

BEGIN;
CREATE TABLE sales (
    sales_date date
    , amount numeric
);
INSERT INTO sales (sales_date , amount)
SELECT
    i
    , (random() * 10)::integer
FROM
    generate_series('2022-01-01'::timestamp , '2022-01-20'::timestamp , interval '1 day') g (i);
ALTER TABLE sales
    ADD COLUMN friday date;
UPDATE
    sales
SET
    friday = (date_trunc('week' , sales_date) + interval '4 day')::date;
ALTER TABLE sales
    ADD COLUMN compute_friday date;
UPDATE
    sales
SET
    compute_friday = CASE WHEN sales_date > friday THEN
        (friday + interval '7 days')::date
    ELSE
        friday
    END;
COMMIT;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文