按年和月分组并获得一个月的最小值,日期

Posted

技术标签:

【中文标题】按年和月分组并获得一个月的最小值,日期【英文标题】:Group by year and month and get min value for a month, with the date 【发布时间】:2018-11-06 07:31:54 【问题描述】:

这就是我的桌子的样子

Column  |     Type     |
--------+--------------+
id      | integer      |
date    | date         |
open    | numeric(9,2) |
close   | numeric(9,2) |
low     | numeric(9,2) |
high    | numeric(9,2) |

我想获取给定月份所有月份的最低收盘价的日期。

这是我设法得到的,

SELECT 
    temp_table.year, temp_table.month, MIN(close)
FROM
    (
        SELECT 
            date_trunc('year', date) as year, date_trunc('month', date) as month, date, close 
        FROM
            sensex_sensex
        GROUP BY 
            year, month, date, close
        ORDER BY 
            year, month
    ) AS temp_table
GROUP BY
    temp_table.year, temp_table.month
ORDER BY
    temp_table.year DESC, temp_table.month DESC;

这给了我年份月份和最低收盘价。 但是当我尝试添加日期时,我得到了所有行,而不是按年和月分组。 我该如何获得结果

Year | Month | Date of Lowest Close in a Month | Lowest Close in a Month

另外,

我还希望能够找到一个月内至少 5 个关闭值及其日期,再次按年和月分组。

【问题讨论】:

【参考方案1】:

demo:db<>fiddle

使用window function MIN 选择每帧的最小值(在您的情况下为月份)。

SELECT
    extract('year' FROM mydate) as year,
    extract('month' FROM mydate) as month,
    mydate, close
FROM (
    SELECT
        mydate,
        close,
        MIN(close) OVER (PARTITION BY date_trunc('month', mydate)) as min_close
    FROM
        temp_table
) s
WHERE close = min_close

您可以使用ROW_NUMBER 代替MIN。如果您不仅要选择一个最小值,而且要选择两个或五个最小的数字 (n),这将有助于您:

SELECT
    extract('year' FROM mydate) as year,
    extract('month' FROM mydate) as month,
    mydate, close
FROM (
    SELECT
        mydate,
        close,
        ROW_NUMBER() OVER (PARTITION BY date_trunc('month', mydate) ORDER BY close) as rn
    FROM
        temp_table
) s
WHERE rn <= n              -- n is the number of values you get.

您真的需要可以根据日期轻松计算的年份和月份的单独列吗?

【讨论】:

扩展答案和小提琴 n 最小值 谢谢,正是我需要的。是的,你是对的,当我从日期中提取它时,我不会将月份和年份分开。【参考方案2】:

使用关联子查询

SELECT 
  date_trunc('year', date) as year, date_trunc('month', date) as month, date, close 
            FROM
                sensex_sensex t where t.close=( select min(close)
                                    from 
                                   sensex_sensex t1
  where   date_trunc('year', t1.date)=date_trunc('year', t.date)
    and
     date_trunc('month', t1.date)=date_trunc('month', t.date)
 )

或者使用窗口函数

with cte (   
    select  
         date_trunc('year', date) as year,
         date_trunc('month', date) as month, date, close,
         min (close) over ( order by date ) rn 
    FROM
         sensex_sensex
) select * from cte where cte.rn=1

【讨论】:

我需要一个月的最小收盘日期,这给了我该月的最小日期【参考方案3】:

您可以使用相关子查询

     SELECT date_trunc('year', date) as year, date_trunc('month', date) as month, date, close 
     FROM sensex_sensex a where close in 
    (select min(close) from sensex_sensex b 
     where date_trunc('year', a.date)=date_trunc('year', b.date) 
     and date_trunc('month', a.date)=date_trunc('month', b.date))

或者你可以窗口函数 row_number()

select * from
(
SELECT date_trunc('year', date) as year, date_trunc('month', date) as month, date, close,row_number() over(partition by date_trunc('year', date),date_trunc('month', date) order by close) as rn
         FROM sensex_sensex
)A where rn=1

【讨论】:

错误:架构“a”不存在 @at14,更新了它 - 一个错字错误 现在可以了。但它有点慢,大约需要 40 秒才能运行。该表只有 9k 行。有什么想法让它更快吗? 你可以使用窗口功能试试看@at14

以上是关于按年和月分组并获得一个月的最小值,日期的主要内容,如果未能解决你的问题,请参考以下文章

如何简化 Laravel 查询以按年搜索日期并按月分组

我需要从结构为 yyyyMMddHHmmss 20170227141500 的时间戳中按年和月分组

如何使用 CouchDB 按年和月对条目进行分组?

如何找到r中不同日期的最小值

sql中如何把具体日期转化为按月排序?

Spark reducebykey - 列表元素的最小值