在SQL Server中查找聚合的MAX行

时间:2016-11-01 00:04:37

标签: sql sql-server

似乎无法在SQL Server中解决这个问题。

两张桌子:

状态:

id   proj   status   changedate
-------------------------------
1    1      1        2015-01-01
2    1      3        2016-01-01
3    1      2        2016-05-01
4    2      1        2016-01-01
... etc

项目:

id    title        active
----------------------------
1     My project   1
2     No more      0 

现在我想列出所有具有最新状态ID的活动项目。我尝试了各种查询,但最终出现了错误。

在包括HAVING在内的其他解决方案中试过这个,但没有运气:

SELECT projects.id, projects.title, statuses.status
FROM projects
INNER JOIN statuses ON statuses.proj = projects.id  
WHERE projects.active = 1 
  AND statuses.changedate = MAX(statuses.changedate)    

那里有任何SQL Server向导吗?

3 个答案:

答案 0 :(得分:4)

使用您所在的路径,您需要一个子查询:

SELECT p.id, p.title, s.status
FROM projects p INNER JOIN
     statuses s
     ON s.proj = p.id  
WHERE p.active = 1 AND
      s.changedate = (SELECT MAX(s2.changedate)   
                      FROM statuses s2
                      WHERE s2.proj = p.id
                     );

更典型的解决方案使用ROW_NUMBER()

SELECT p.id, p.title, s.status
FROM projects p INNER JOIN
     (SELECT s.*,
             ROW_NUMBER() OVER (PARTITION BY s.proj ORDER BY s.changedate DESC) as seqnum
      FROM statuses s
     ) s
     ON s.proj = p.id AND seqnum = 1
WHERE p.active = 1;

更难以理解的方式是使用APPLY

SELECT p.*, s.status
FROM projects p OUTER APPLY
     (SELECT TOP 1 s.*
      FROM status s
      WHERE s.proj = p.id
      ORDER BY s.changedate DESC
     ) s
WHERE p.active = 1;

嗯,这是不可思议的,你以前从未见过APPLY

答案 1 :(得分:1)

另一种选择是使用TOP 1 WITH TIES并使用row_number()命令:

select top 1 WITH TIES 
t1.status
, t1.changedate
, p.title
from statuses t1
inner join projects p on p.id = t1.proj AND p.active = 1
order by
ROW_NUMBER() OVER(PARTITION BY t1.proj ORDER BY changedate desc)

答案 2 :(得分:1)

这是来自MySql,但SqlServer

的语法应该非常相似
create table status (
    id int,
    proj int,
    status int,
    change_date date
);

create table project (
    id  int,
    title varchar(64),
    active int
);

insert into status values (1,1,1,'2015-01-01');
insert into status values (2,1,3,'2015-01-01');
insert into status values (3,1,2,'2015-01-01');
insert into status values (4,2,1,'2015-01-01');

insert into project values (1,'My project', 1);
insert into project values (2,'No more', 0);
insert into project values (3,'Other project', 1);


select
    p.title,
    max(s.change_date)
from
    project p
    left outer join status s on s.proj = p.id
where
    p.active = 1
group by 
    p.title
;

输出如下:

+ ------------- + ----------------------- +
| title         | max(s.change_date)      |
+ ------------- + ----------------------- +
| My project    | 2015-01-01              |
| Other project |                         |
+ ------------- + ----------------------- +
2 rows