2009-12-10 152 views
0

我有一个看起来像一个表关系返回列第一行数据未在以下组:聚合函数由

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

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

所以每当我只是把一个新行具有稳定的内容改变具有新的stable_contents和当前时间戳的相应的barn_id和stable_number。

这些表格是这样设计的,所以我可以看看一个稳定的,看到它的整个历史。

我想写一个查询,会发现我所有的马厩的当前状态中的所有谷仓,所以我试试这个:

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

在我的测试数据我有这样的一些行谷仓1,稳定的7

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

如果我运行上面的SELECT查询,我得到了谷仓1以下返回行,稳定的7:

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

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

任何想法?

回答

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 
    ) 
+0

我选择这一个,因为替代形式移植到了很好的HQL。感谢所有提交。 – TheBigS 2009-12-10 18:06:54

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)

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 

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

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)上有一个复合索引,以便快速工作。

看到这篇文章在我的博客了解更多详情: