【问题标题】:Postgres SQL query - averages per monthPostgresql 查询 - 每月平均值
【发布时间】:2017-07-17 03:57:41
【问题描述】:

我有两个想要实现的查询。

我有一张这样的桌子......

Date        | Period | Location | Price
2017-01-01      1         A         10
2017-01-01      2         A         15
2017-01-01      1         B         15
2017-01-01      2         B         16

每个日期有 48 个读数(每半小时一个)。

查询 1:我希望获取日期范围内任何给定位置的平均价格,格式如下:

例如2017 年 1 月 1 日至 2017 年 6 月 30 日期间,位置“A”的每期平均价格

  Period 1  | Period 2|  Period 3 ...
       10           11          15

查询 2:我希望任何给定位置的平均价格可以追溯到 x 个月:(期间无关紧要)

Month   |  Average price
january        10
february       12
march          16

任何帮助将不胜感激:)

【问题讨论】:

  • 到目前为止你有没有尝试过?
  • 这里有两个不同的问题。我建议你单独问他们。
  • 你有什么尝试吗?..看起来很简单select查询是所有需要的
  • 我有这个用于第一个查询。其实我更关心第二个查询... SELECT period, avg(price)/10 as price FROM table where location='A' group by period order by period;
  • 对于第一个查询,您希望对周期数据进行透视?

标签: sql postgresql


【解决方案1】:

您列出的第二个查询是一个非常简单的group by 操作。唯一有点棘手的是您需要从列出的日期中提取月份。

select
    date_part('month', t.Date) as month,
    avg(t.Price) as average_price
from
    mytable t
group by
    date_part('month', t.Date)

然而,第一个查询要复杂得多。它涉及crosstab(),如果您还没有启用它,您必须在数据库中启用它。一般的想法是计算每个时期的平均值,然后像在 excel 中一样旋转数据。

select * from crosstab(
'   select
        t.Period
        , avg(t.Price) as avg_price
    from
        mytable t
    group by
        t.Period
    order by
        1
        , 2
'
) as ct(
    "Period" text
    , "1"  int
    , "2"  int
    , "3"  int
    , "4"  int
    , "5"  int
    , "6"  int
    , "7"  int
    , "8"  int
    , "9"  int
    , "10" int
    , "11" int
    , "12" int
)

这个answer有大量关于Postgre的crosstab()的信息

【讨论】:

  • 感谢您的回复。但是我收到以下错误... 错误:无效的源数据 SQL 语句 详细信息:提供的 SQL 必须返回 3 列:rowid、类别和值。 ********** 错误 ********** 错误:无效的源数据 SQL 语句 SQL 状态:22023 详细信息:提供的 SQL 必须返回 3 列:rowid、类别和值。
【解决方案2】:

第一个问题:

你需要一个支点。如果您不想以静态方式执行此操作(在查询中手动命名所有期间列),您可以使用 JSON 以更动态的方式进行:

SQL Fiddle Query

结果:

{"Period 1": 15.0000000000000000, "Period 2": 22.5000000000000000, "Period 3": 100.0000000000000000, "Period 4": 150.0000000000000000}

您会得到一个 JSON 字符串,可用于进一步计算,例如

SELECT json_pivot -> 'Period 2' FROM (/* subquery */)

请看这里:SQL Fiddle: Further calculation

使用 JSON 函数,您可以获得动态的伪数据透视结果。

查询:

SELECT 
    jsonb_object_agg(period, avg) as pivot_json         -- B
FROM (
    SELECT 
        'Period ' || period as period,  AVG(price)      -- A
    FROM 
        period_prices pp
    WHERE 
        location = 'A' 
        AND date BETWEEN '2017-01-01' AND '2017-06-30'
    GROUP BY location, period
)s

A:按位置和周期分组,将周期编号重命名为“Period [number]”

B:jsonb_object_agg 将两列聚合到显示的结果中。

https://www.postgresql.org/docs/current/static/functions-json.html

https://www.postgresql.org/docs/current/static/functions-aggregate.html


第二个问题是一个简单的GROUP BYSQL Fiddle

SELECT
    to_char(pp.date, 'month') as month,    
    avg(pp.price) as avg_price
FROM
    period_prices pp
GROUP BY
    to_char(pp.date, 'month')

您可以按date_part 分组。但是,虽然date_part('month', ...) 为您提供了月份的编号(这是进一步计算的首选解决方案),但您最终希望获得月份的名称。为此,您可以使用to_char() 函数。

https://www.postgresql.org/docs/current/static/functions-formatting.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 2018-12-19
    • 2019-07-06
    • 1970-01-01
    • 2013-03-25
    相关资源
    最近更新 更多