2010-01-21 64 views
2

所以我知道这个问题并不是新问题,但我试图围绕它来理解最佳方式来处理这种情况。查询基于另一个值的聚合的唯一值,同时完全按第三个值进行分组

说我有一个假设表“X”,看起来像这样:

GroupID ID (identity) SomeDateTime 
-------------------------------------------- 
1  1000  1/1/01 
1  1001  2/2/02 
1  1002  3/3/03 
2  1003  4/4/04 
2  1004  5/5/05 

我想查询它所以结果集是这样的:

---------------------------------------- 
1  1002  3/3/03 
2  1004  5/5/05 

基本上我想要的是MAX SomeDateTime值按我的GroupID列分组。踢球者是我不想要分组的ID列, 我只想知道对应于MAX SomeDateTime的'ID'。

我知道一个假的解决办法是:

;WITH X1 as (
    SELECT MAX(SomeDateTime) as SomeDateTime, GroupID 
    FROM X 
    GROUP BY GroupID 
) 
SELECT X1.SomeDateTime, X1.GroupID, X2.ID 
FROM X1 
    INNER JOIN X as X2 
     ON X.DateTime = X2.DateTime 

但是,这并没有解决的事实,一个DateTime可能不是唯一的。像这样加入DateTime看起来很sl sl。

另一种伪解决方案是:

SELECT X.GroupID, MAX(X.ID) as ID, MAX(X.SomeDateTime) as SomeDateTime 
FROM X 
GROUP BY X.GroupID 

但没有保证ID实际上将匹配一行SomeDateTime从何而来。

减少了三分之一有用的选项可能是:

SELECT TOP 1 X.GroupID, X.ID, X.SomeDateTime 
FROM X 
WHERE X.GroupID = 1 
ORDER BY X.SomeDateTime DESC 

但很明显,只有一个单一的,众所周知,GroupID工作。我希望能够在GroupID和/或ID上加入此结果集。

有谁知道任何聪明的解决方案?窗口函数有什么好用处?

谢谢!

回答

1

我认为这会做你想做的。

;WITH X1 
AS 
(
    SELECT SomeDateTime 
      ,GroupID 
      ,ID 
      ,ROW_NUMBER() OVER (PARTITION BY GroupID 
           ORDER BY SomeDateTime DESC 
           ) AS rn 
    FROM X 
) 
SELECT SomeDateTime 
     ,GroupID 
     ,ID 
FROM X1 
WHERE rn = 1 
+0

它看起来像这可能是我后我。我不需要在CTE中使用GROUP BY,但是...会继续使用这一点。谢谢! – 2010-01-21 15:44:46

+0

@Justin - 我已根据您的评论更正了我的答案。 – 2010-01-21 16:51:16

1

您的第一个解决方案是正确的。我已经写是作为一个内部的选择(注意,语法innnersleect由DBMS ifferent,我已经习惯了DB2这些天,所以这就是你:-):

选择g.groupid, g.id,g.somedatetime

从XG,(选择s.groupid,最大值(s.somedatetime)从XS组由s.groupid)SI

其中g.groupid = s.groupid和g。 somedatetime = si.somedatetime;

但是,正如你指出的,如果somedatetime一个ID不是唯一的,那么你会得到多行对每个这样的组ID。为了消除这种情况,您需要额外的子选择来获取max(somedatetime)的max(id)。非常凌乱:

选择g.groupid,g.id,g。somedatetime

从XG,(选择s.groupid,最大值(s.somedatetime),如通过从s.groupid XS组的maxDate)SI,

(选择i.groupid,最大值(i.id)作为maxid ,i.somedatetime from xi其中i.groupid = si.groupid和i.somedatetime = si.maxdate group by i.groupid,i.somedatetime)si2

其中g.groupid = s.groupid和g.id = maxid和g.somedatetime = maxdate;

0

您也可以使用交叉的组合应用功能和顶部(1)来解决这个

select 
distinct(GroupId) 
,maxvales.SomeDateTime 
from 
X as outerX 
cross apply 
    (select top(1) SomeDateTime from X as innerX where innerX.GroupID = outerX.GroupID order by SomeDateTime desc) as maxvales 
相关问题