1

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

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);

我将如何编写一个查询来返回两个日期之间的第一个最小重量最小重量发生的日期?

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

伪 SQL:

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

4 回答 4

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;

不支持不实现窗口函数(如 MySQL)的 RDBMS。

标准 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 支持 -在 Wikipedia 上查找列表

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


解决评论中的问题,我在此处引用有关 ORDER BY 的手册

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

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

于 2012-07-16T21:20:29.650 回答
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”最小重量......我假设这意味着最小重量的最早日期。

于 2012-07-16T21:09:03.760 回答
0

您可能会请求 SELECT * ORDER BY weight ASC LIMIT 1(大多数 DB 支持 LIMIT),或者根本不使用 LIMIT 而只从游标中检索第一行。

否则,您需要一个 JOIN 来获取最小值,然后检索最小值确实发生的日期;并且在多个日期达到最小值的情况下,您仍然需要 LIMIT 和/或一次提取。

于 2012-07-16T21:08:53.777 回答
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 中的任何等价物。

于 2012-07-16T21:21:05.990 回答