如何编写此类查询(返回每行的最新可用数据)

时间:2012-01-29 13:17:42

标签: mysql sql greatest-n-per-group

我有一个像这样定义的表:

CREATE TABLE mytable (id            INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), 
                      user_id       INT REFERENCES user(id) ON UPDATE CASCASE ON DELETE RESTRICT,
                      amount        REAL NOT NULL CHECK (amount > 0),
                      record_date   DATE NOT NULL
                     );
CREATE UNIQUE INDEX idxu_mybl_key ON mytable (user_id, amount, record_date);

我想编写一个包含两列的查询:

  • USER_ID
  • 金额

给定用户的返回结果集中应该只有一个条目。此外,返回的金额数字应该是用户的最后一次重新计算金额(即MAX(record_date)。

由于权重是针对不同用户在不同日期记录的,因此产生了复杂性,因此所有用户都没有单一的LAST record_date。

我如何编写(最好是ANSI SQL)查询以返回前面提到的列,但确保它只返回返回的用户的最后记录金额?

顺便说一下,在查询中返回'record_date'列可能是个好主意,这样就可以轻松(ier)验证查询是否按要求运行。

我使用MySQL作为我的后端数据库,但理想情况下,如果可能,查询应该是db不可知的(即ANSI SQL)。

4 个答案:

答案 0 :(得分:3)

首先,您需要为每个用户提供最后一个record_date

select user_id, max(record_date) as last_record_date
from mytable
group by user_id

现在,您可以使用mytable本身加入之前的查询,以获取此记录日期的amount

select 
      t1.user_id, last_record_date, amount
from 
      mytable  t1
  inner join
      ( select user_id, max(record_date) as last_record_date
        from mytable
        group by user_id 
      ) t2
    on  t1.user_id = t2.user_id 
    and t1.record_date = t2.last_record_date

出现问题,因为用户可以为同一last_record_date(具有不同金额)的多行。然后你应该得到其中一个,样本(得到不同金额的最大值):

select 
      t1.user_id, t1.record_date as last_record_date, max(t1.amount)
from 
      mytable  t1
  inner join
      ( select user_id, max(record_date) as last_record_date
        from mytable
        group by user_id 
      ) t2
    on  t1.user_id = t2.user_id 
    and t1.record_date = t2.last_record_date
group by t1.user_id, t1.record_date

答案 1 :(得分:1)

我现在不讨论MySQL,但在一般的SQL中你需要一个子查询。您必须加入计算最大record_date的查询,并使用计算相应金额的原始记录。大概是这样的:

SELECT B.*
FROM 
      (select user_id, max(record_date) max_date from mytable group by user_id) A
  join 
      mytable B
  on A.user_id = B.user_id and A.max_date = B.record_date

答案 2 :(得分:0)

SELECT datatable.* FROM
mytable AS datatable 
INNER JOIN (
  SELECT user_id,max(record_date) AS max_record_date FROM mytable GROUP BS user_id
) AS selectortable ON
  selectortable.user_id=datatable.user_id
  AND
  selectortable.max_record_date=datatable.record_date

在某些SQL中你可能需要

SELECT MAX(user_id), ...

在selectortable视图中,而不仅仅是SELECT user_id,...

答案 3 :(得分:0)

最大值的定义:没有比这个值更大(或“更近期”)的值。这自然会导致NOT EXISTS查询,该查询应该可以在任何DBMS中使用。

SELECT user_id, amount 
FROM mytable mt
WHERE mt.user_id = $user
AND NOT EXISTS ( SELECT *
    FROM mytable nx
    WHERE nx.user_id = mt.user_id
    AND nx.record_date > mt.record_date
    )
;

BTW:您的表定义允许给定{id,date}存在多个记录,但具有不同的金额。此查询将全部返回。