查找表中的第一个最低值和发生最低值的日期

时间:2012-07-16 21:02:43

标签: sql postgresql

如果我有一个包含以下架构的表:

CREATE TABLE diet_watch (
  entry_date date NOT NULL,
  weight     double precision NOT NULL
);

INSERT INTO diet_watch VALUES ('2001-01-01', 128.2);
INSERT INTO diet_watch VALUES ('2001-01-02', 121.0);
INSERT INTO diet_watch VALUES ('2001-01-03', 122.3);
INSERT INTO diet_watch VALUES ('2001-01-04', 303.7);
INSERT INTO diet_watch VALUES ('2001-01-05', 121.0);
INSERT INTO diet_watch VALUES ('2001-01-06', 128.0);

我如何编写一个查询,以便在两个日期之间返回 FIRST 最小权重 AND 最小权重发生的日期?

理想情况下,这将是ANSI-SQL,即db不可知。如果我不得不被迫选择SQL风格,它将是PostgreSQL,因为那是我正在使用的数据库。

PSEUDO SQL:

SELECT min(entry_date), min(weight)
FROM   diet_watch
where  entry date between date1 and date2
group  by entry_date;

4 个答案:

答案 0 :(得分:3)

简单快捷的解决方案:

SELECT weight, entry_date
FROM   diet_watch
WHERE  entry_date BETWEEN '2001-01-02' AND '2001-01-06'
ORDER  BY 1, 2
LIMIT  1;

适用于PostgreSQL或MySQL以及其他可能(不在Oracle或MS SQL Server中)。

标准SQL(SQL:2003):

SELECT weight, entry_date
FROM  (
    SELECT weight, entry_date
          ,row_number() OVER (ORDER BY weight, entry_date) AS rn
    FROM   diet_watch
    WHERE  entry_date between '2001-01-02' and '2001-01-06'
    ) AS x
WHERE rn = 1;

不支持未实现窗口功能的RDBMS(如MySQL)。

标准SQL变体(SQL:2008):

SELECT weight, entry_date
FROM   diet_watch
WHERE  entry_date BETWEEN '2001-01-02' AND '2001-01-06'
ORDER  BY weight, entry_date
FETCH  FIRST 1 ROWS ONLY;

只有少数RDBMS支持 - 找到list on Wikipedia

支持所有这些的唯一 RDBMS是PostgreSQL(v8.4或更高版本)。


在评论中提问,我引用the manual here about ORDER BY

  

每个表达式可以是输出列的名称或序号   (SELECT列表项),或者它可以是由...形成的任意表达式   输入列值。

强调我的。它只是一个语法快捷方式,由许多RDBMS支持。 SQL Server显然不在其中。

答案 1 :(得分:2)

SELECT min(entry_date), min(weight) from diet_watch where weight = (
    SELECT MIN(weight) as wt from diet_watch where entry_date between date1 and date2
) and entry_date between date1 and date2

[编辑:答案略有调整,因为看起来问题已从找到最小日期的重量更改为最小重量日期]

此外,该问题要求“FIRST”最小重量......我假设这意味着最小重量的最早日期。

答案 2 :(得分:0)

您可以请求SELECT * ORDER BY权重ASC LIMIT 1(大多数DB支持LIMIT),或者根本不使用LIMIT,只检索光标的第一行。

否则,您需要JOIN才能获得最小值,然后检索最小值确实发生的日期;如果达到最低限度的多个日期,您仍然需要LIMIT和/或单次获取。

答案 3 :(得分:0)

根据Gerrat的回答,可以通过entry_date命令并抓住第一行。

SELECT top 1 entry_date, weight
FROM diet_watch
WHERE weight = (SELECT MIN(weight) as wt from diet_watch)
ORDER BY entry_date

编辑:这是SQL Server代码。但是你可以使用postgre中的等价物。