【问题标题】:Postgresql convert query to view with generic month parameterPostgresql 使用通用月份参数将查询转换为视图
【发布时间】:2018-06-09 01:01:23
【问题描述】:

我有一个非常大的查询。

那个查询中,我必须定义一个日期范围,例如x和y之间的日期。日期范围的定义是另一个选择查询中的一个选择查询。

我希望将此查询转换为视图。这样它就可以按月对所有结果进行分组,例如日期在“2000-01-01”和“2000-01-31”之间。

有没有办法让它做到这一点,例如

where date in unique month

这样我就可以进行另一个查询,只是

select * from temp_view where (max_start_date, max_end_date) overlaps ('2000-01-01', '2000-01-31')

有点难以解释...

有点像在查询中输入所有可能的月份。

这是一个示例查询

    data_table
    fruit  | start_date  |  end_date
    APPLE    2000-01-14     2000-01-20
    APPLE  | 2000-01-20  |  2000-02-05
    ORANGE | 2000-01-01  |  2000-02-10

    value_table (there is a reading every day)
   trading_date | fruit  | value
    2000-01-01   APPLE    1
    2000-01-02   APPLE    1.2
    2000-01-03   APPLE    2.2
    ...
    2000-02-15   APPLE   4.4
    2000-02-16   APPLE   5.2
    ...
    2000-01-01   ORANGE    2
    2000-01-02   ORANGE    3
    2000-01-03   ORANGE    1
    ...
    2000-02-15   ORANGE   2.4
    2000-02-16   ORANGE   2.2

查询:

    with prequery as (SELECT   value, start_date, end_date
        from data_table
            )     
            SELECT 
                month,
                some_value,
                start_date,
                end_date,
                sum(daily_value)
                FROM  prequery
                INNER JOIN value_table
                on fruit=value_table.fruit  
                and trading_date between start_date and  end_date
                ->[[[and trading_date between '2000-01-01' and '2000-01-31']]]<- dont want this.  Want it to group by months.

输出(不包括所有值,只是为了显示我的目标)

Month  |  value  |  start_date   | end_date   | sum   |    
2000-01   APPLE     2000-01-20    2000-02-05    (sum of all values between start and end dates in January for APPLE)
2000-02   APPLE     2000-01-14    2000-01-20    (sum of all values between start and end dates in February for APPLE)

【问题讨论】:

  • 样本数据和期望的结果真的很有帮助。
  • 嗨,戈登,我添加了一些示例数据来澄清这个问题。达林

标签: sql postgresql


【解决方案1】:

您是否正在寻找可以选择一个月的第一天和最后一天的视图?

这将创建一个视图months,其中包含从 1970 年 1 月到 2070 年 12 月的所有月份。

CREATE VIEW months
AS
WITH RECURSIVE cte(i, number_of_year, number_of_month, first_day, last_day)
AS
(
SELECT 1 i,
       0 / 12 + 1970 number_of_year,
       0 % 12 + 1 number_of_month,
       (lpad((0 / 12 + 1970)::text, 4, '0') || '-' || lpad((0 % 12 + 1)::text, 2, '0') || '-01')::timestamp first_day,
       (lpad((0 / 12 + 1970)::text, 4, '0') || '-' || lpad((0 % 12 + 1)::text, 2, '0') || '-01')::timestamp + INTERVAL '1 month - 1 day' last_day
UNION ALL
SELECT i + 1 i,
       i / 12 + 1970 number_of_year,
       i % 12 + 1 number_of_month,
       (lpad((i / 12 + 1970)::text, 4, '0') || '-' || lpad((i % 12 + 1)::text, 2, '0') || '-01')::timestamp first_day,
       (lpad((i / 12 + 1970)::text, 4, '0') || '-' || lpad((i % 12 + 1)::text, 2, '0') || '-01')::timestamp + INTERVAL '1 month - 1 day' last_day
       FROM cte
       WHERE i / 12 + 1970 <= 2070
)
SELECT number_of_year,
       number_of_month,
       first_day,
       last_day
       FROM cte;

但我建议实现这一点以获得更好的性能。

CREATE TABLE months
AS
WITH RECURSIVE cte(i, number_of_year, number_of_month, first_day, last_day)
AS
(
SELECT 1 i,
       0 / 12 + 1970 number_of_year,
       0 % 12 + 1 number_of_month,
       (lpad((0 / 12 + 1970)::text, 4, '0') || '-' || lpad((0 % 12 + 1)::text, 2, '0') || '-01')::timestamp first_day,
       (lpad((0 / 12 + 1970)::text, 4, '0') || '-' || lpad((0 % 12 + 1)::text, 2, '0') || '-01')::timestamp + INTERVAL '1 month - 1 day' last_day
UNION ALL
SELECT i + 1 i,
       i / 12 + 1970 number_of_year,
       i % 12 + 1 number_of_month,
       (lpad((i / 12 + 1970)::text, 4, '0') || '-' || lpad((i % 12 + 1)::text, 2, '0') || '-01')::timestamp first_day,
       (lpad((i / 12 + 1970)::text, 4, '0') || '-' || lpad((i % 12 + 1)::text, 2, '0') || '-01')::timestamp + INTERVAL '1 month - 1 day' last_day
       FROM cte
       WHERE i / 12 + 1970 <= 2070
)
SELECT number_of_year,
       number_of_month,
       first_day,
       last_day
       FROM cte;

我想你会这样查询它:

SELECT first_day,
       last_day
       FROM months
       WHERE number_of_year = <year>
             AND number_of_month = <month>;

然后也创建如下索引来支持它。

CREATE INDEX months_number_of_year_number_of_month_first_day_last_day
             ON months (number_of_year,
                        number_of_month,
                        first_day,
                        last_day);

【讨论】:

    猜你喜欢
    • 2021-07-25
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 2014-04-01
    相关资源
    最近更新 更多