聚合函数返回不在组中的列的第一行数据

时间:2009-12-10 15:49:10

标签: sql mysql

我有一个表关系,如下所示:

barn
------
PK barn_id
<other columns>

stable
---------
PK stable_id
FK barn_id
stable_number
stable_contents
timestamp

因此,无论何时稳定更改的内容,我只需将相应的barn_id和stable_number与新的stable_contents和当前时间戳放在一个新行中。

这些表是按照这种方式设计的,所以我可以看一下某个稳定的并看到它的整个历史。

我正在尝试编写一个查询,它会找到所有谷仓中所有马厩的当前状态,所以我试试这个:

SELECT barn_id, stable_number, max(timestamp), stable_contents
FROM stable
GROUP BY barn_id, stable_number

在我的测试数据中,我有一些像barn 1这样的行,稳定7

1 | 7 | 2009-12-09 10:00:00 | empty
1 | 7 | 2009-12-10 10:30:00 | show horse

如果我运行上面的SELECT查询,我会为barn 1返回以下行,稳定7:

1 | 7 | 2009-12-10 10:30:00 | empty

它获得了正确的最大时间戳,只是错误的stable_contents。

有什么想法吗?

4 个答案:

答案 0 :(得分:0)

您需要使用子查询:

SELECT barn_id, stable_number, timestamp, stable_contents
FROM stable
WHERE (barn_id, stable_number, timestamp) IN 
(SELECT barn_id, stable_number, max(timestamp) as timestamp
FROM stable
GROUP BY barn_id, stable_number)

除非您告诉它,否则数据库无法知道您希望来自具有最高时间戳的行的稳定内容。您可以查询多个聚合子句max(timestamp)min(timestamp)等。

答案 1 :(得分:0)

SELECT s.*
FROM (
    SELECT barn_id, stable_number, max(timestamp) as timestamp
    FROM stable
    GROUP BY barn_id, stable_number) d
INNER JOIN stable s ON s.barn_id = d.barn_id
                       AND s.stable_number = d.stable_number
                       AND s.timestamp = d.timestamp

这通常是拥有两个表的更好方法:一个包含当前状态,另一个包含历史数据。

答案 2 :(得分:0)

它确实应该给你一个错误,而不是返回未定义的数据,因为你试图得到不在你的GROUP BY(stable_contents)中的非聚合数据。我将使用以下查询,该查询查找稳定的所有行,其中对于相同的稳定版,其后面没有一行:

SELECT
     T1.barn_id,
     T1.stable_number,
     T1.timestamp,
     T1.stable_contents
FROM
     Stable AS T1
LEFT OUTER JOIN Stable AS T2 ON
     T2.barn_id = T1.barn_id AND
     T2.stable_number = T1.stable_number AND
     T2.timestamp > T1.timestamp
WHERE
     T2.barn_id IS NULL     -- The only way for this to be NULL is if no match was found

可替换地:

SELECT
     T1.barn_id,
     T1.stable_number,
     T1.timestamp,
     T1.stable_contents
FROM
     Stable AS T1
WHERE
     NOT EXISTS
     (
          SELECT
               *
          FROM
               Stable AS T2
          WHERE
               T2.barn_id = T1.barn_id AND
               T2.stable_number = T1.stable_number AND
               T2.timestamp > T1.timestamp
     )

答案 3 :(得分:0)

SELECT  s.*
FROM    barn b
JOIN    stable s
ON      stable_id = 
        (
        SELECT  stable_id
        FROM    stable si
        WHERE   si.barn_id = b.id
        ORDER BY
                barn_id DESC, timestamp DESC, stable_id DESC
        )

确保stable (barn_id, timestamp, stable_id)上有一个综合索引,以便快速开始工作。

有关详细信息,请参阅我的博客中的这篇文章: