如何使用聚合函数获取MySQL查询中分组记录的第一个和最后一个记录?

时间:2009-09-04 14:20:15

标签: mysql aggregate-functions

我正在尝试获取“分组”记录的第一个和最后一个记录 更确切地说,我正在做这样的查询

SELECT MIN(low_price), MAX(high_price), open, close
FROM symbols
WHERE date BETWEEN(.. ..)
GROUP BY YEARWEEK(date)

但我想获得该组的第一个和最后一个记录。它可以通过做大量的请求完成,但我有一个非常大的表。

是否有一个(如果可能的话处理时间很短)用MySQL做这个的方法?

4 个答案:

答案 0 :(得分:53)

您想使用GROUP_CONCATSUBSTRING_INDEX

SUBSTRING_INDEX( GROUP_CONCAT(CAST(open AS CHAR) ORDER BY datetime), ',', 1 ) AS open
SUBSTRING_INDEX( GROUP_CONCAT(CAST(close AS CHAR) ORDER BY datetime DESC), ',', 1 ) AS close 

这避免了昂贵的子查询,我发现它通常对这个特定问题更有效。

查看两个功能的手册页以了解他们的论点,或者访问本文,其中包含有关如何执行timeframe conversion in MySQL以获取更多解释的示例。

答案 1 :(得分:2)

尝试此操作以...开始:

Select YearWeek, Date, Min(Low_Price), Max(High_Price)
From
   (Select YEARWEEK(date) YearWeek, Date, LowPrice, High_Price
    From Symbols S
    Where Date BETWEEN(.. ..)
    GROUP BY YEARWEEK(date)) Z
Group By YearWeek, Date

答案 2 :(得分:0)

以下是针对此特定问题的具体解决方案: http://topwebguy.com/first-and-last-in-mysql-a-working-solution/ 这几乎和在MySQL中使用FIRST和LAST一样简单。

我将包含实际提供解决方案的代码,但您可以查看整个文本:

SELECT
word ,  

(SELECT a.ip_addr FROM article a
WHERE a.word = article.word
ORDER BY a.updated  LIMIT 1) AS first_ip,

(SELECT a.ip_addr FROM article a
WHERE a.word = article.word
ORDER BY a.updated DESC LIMIT 1) AS last_ip

FROM notfound GROUP BY word;

答案 3 :(得分:-1)

假设您想要具有最低low_price和最高high_price的记录的ID,您可以将这两列添加到您的查询中,

SELECT 

(SELECT id ORDER BY low_price ASC LIMIT 1) low_price_id,
(SELECT id ORDER BY high_price DESC LIMIT 1) high_price_id,

MIN(low_price), MAX(high_price), open, close
FROM symbols
WHERE date BETWEEN(.. ..)
GROUP BY YEARWEEK(date)

如果效率是一个问题,你应该为'year_week'添加一个列,添加一些覆盖索引,并将查询拆分为两个。

'year_week'列只是设置为YEARWEEK(日期)值的INT,并且每当更新'date'列时都会更新。这样您就不必为每个查询重新计算它,并且可以将其编入索引。

新的覆盖索引应如下所示。订购很重要。 KEY yw_lp_id(year_week,low_price,id), KEY yw_hp_id(year_week,high_price,id)

然后您应该使用这两个查询

SELECT 
(SELECT id ORDER BY low_price ASC LIMIT 1) low_price_id,
MIN(low_price), open, close
FROM symbols
WHERE year_week BETWEEN(.. ..)
GROUP BY year_week

SELECT 
(SELECT id ORDER BY high_price DESC LIMIT 1) high_price_id,
MAX(high_price), open, close
FROM symbols
WHERE year_week BETWEEN(.. ..)
GROUP BY year_week

覆盖索引非常有用。请查看this以获取更多详细信息。