有没有办法找到分组数据的TOP X记录?

时间:2010-06-01 22:07:24

标签: tsql sybase greatest-n-per-group

我正在使用Sybase 12.5服务器,我有一个如下定义的表:

CREATE TABLE SomeTable(
    [GroupID] [int] NOT NULL,
    [DateStamp] [datetime] NOT NULL,
    [SomeName] varchar(100),
    PRIMARY KEY CLUSTERED (GroupID,DateStamp)
)

我希望能够按[GroupID]列出[DateStamp]中最新的X记录。踢球者是X> 1,所以普通的旧MAX()不会削减它。我假设有一个非常讨厌的方法用游标和什么不做,但我想知道是否有一个更简单的方法没有那些东西。

我知道我错过了一些显而易见的东西,我会因为没有得到它而踢我自己,但是......我没有得到它。请帮忙。

有没有办法找到TOP X记录,但是有分组数据?

2 个答案:

答案 0 :(得分:3)

根据在线手册,Sybase 12.5支持WINDOW函数和ROW_NUMBER(),但它们的语法略有不同于标准SQL。

尝试这样的事情:

SELECT SP.*
FROM (
    SELECT *, ROW_NUMBER() OVER (windowA ORDER BY [DateStamp] DESC) AS RowNum
    FROM SomeTable
    WINDOW windowA AS (PARTITION BY [GroupID])
) AS SP
WHERE SP.RowNum <= 3
ORDER BY RowNum DESC;

我没有Sybase的实例,所以我没有测试过这个。我只是从文档中合成这个例子。


我犯了一个错误。我正在查看的文档是Sybase SQL Anywhere 11.似乎Sybase ASA根本不支持WINDOW子句,即使在最新版本中也是如此。

这是另一个可以完成同样事情的查询。您可以使用自联接将SomeTable的每一行与具有相同GroupID和更高版本DateStamp的所有行匹配。如果以后有三个或更少的行,那么我们就有前三个中的一个。

SELECT s1.[GroupID], s1.[Foo], s1.[Bar], s1.[Baz]
FROM SomeTable s1
LEFT OUTER JOIN SomeTable s2
  ON s1.[GroupID] = s2.[GroupID] AND s1.[DateStamp] < s2.[DateStamp]
GROUP BY s1.[GroupID], s1.[Foo], s1.[Bar], s1.[Baz]
HAVING COUNT(*) < 3
ORDER BY s1.[DateStamp] DESC;

请注意,必须列出SELECT列表中与GROUP BY子句中列出的列相同的列。基本上,您希望此查询返回的s1中的所有列。

答案 1 :(得分:1)

这是一种非常难以捉摸的方式!

SELECT GroupID, DateStamp, SomeName
FROM SomeTable ST1
WHERE X < 
    (SELECT COUNT(*) 
     FROM SomeTable ST2 
     WHERE ST1.GroupID=ST2.GroupID AND ST2.DateStamp > ST1.DateStamp)

编辑比尔的解决方案非常受欢迎。