从表中检索每组中的前1和2条记录

时间:2011-11-11 15:02:43

标签: sql-server-2008 tsql

我有一个查询需要获得每个成员心愿单中的第一和第二高的sku。以下查询有效,但需要时间太长,因为大约有900万用户,每个用户有大约10个愿望清单项目,因此您可以看到下面的查询永远不会完成。

SELECT MAX(CASE WHEN wl.rank = 1 THEN wl.SKU ELSE NULL END) AS [highestSku],
       MAX(CASE WHEN wl.rank = 2 THEN wl.SKU ELSE NULL END) AS [secondHighestSku],
FROM Member m
     LEFT JOIN (SELECT *
                 FROM (SELECT DENSE_RANK() OVER (PARTITION BY wl.MemberID ORDER BY wli.Price DESC) AS rank, wl.MemberID, wli.SKU
                       FROM WishListItem wli
                            INNER JOIN WishList wl ON wli.WishListID = wl.ID) T1) w ON w.MemberID = m.ID

我的问题是,有没有更好的方法来获得每个用户的第一个和第二个记录?如果没有,有没有办法可以优化此查询?理想情况下,如果我可以从排序查询(带有DENSE_RANK()的那个)中撤回的tiems数量,那将帮助我解决问题。我想做一些像WHERE DENDS_RANK()< = 2这样的事情,但那是不可能的,而且在括号之外做它会破坏灵魂的目的。

此外,这只是查询的一部分。实际上我在更多表中有更多的左连接,这些表具有尽可能多的项目,我需要为每个用户获取前1和2条记录。

这需要在一个查询中完成,或者尽可能在一个查询中完成,因为我将它放在数据表中。我也可以减少记录数量,即。 TOP 1000,并打破查询,但我需要能够从我离开的地方继续...还有,我确实尝试了TOP 1000,并且在10分钟后,我取消了查询,因为我需要获得全部9百万记录。

1 个答案:

答案 0 :(得分:0)

我会抓取一个相对较小的数据子集,将其粘贴在一个表变量中,并运行查询而不是主表(可能非常“忙”)表:

DECLARE @Member TABLE
(
    ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
    -- add necessary columns to this definition.
)

INSERT INTO @Member (field1, field2...)
SELECT field1, field2  -- etc. 
FROM YourTables
WHERE SomeCriteria = Whatever

确保WHERE子句定义比生产表更窄的数据子集。如果性能仍然存在,您可以为要加入的其他表创建表变量,然后在最终查询中使用它们。