SQL Server DISTINCT与ROW_NUMBER()的分页并不明显

时间:2011-11-17 00:34:02

标签: sql sql-server pagination distinct

好的,基本上我的DISTINCT使用ROW_NUMBER()变得无用,我需要避免这种情况,因为它会导致重复的结果(除了当然的唯一数量!)

所以我正在寻找的是一个查询,它会工作相同但没有重复的行,因为num是唯一的:

WITH t AS
(
   SELECT DISTINCT *, ROW_NUMBER() OVER (ORDER BY Date) AS num 
   FROM Original_Import 
   LEFT JOIN eqcas.dbo.BASE_PROXY_VIEW_WITHTARGET ON ADName = Targetuser
   WHERE (BaseProxy = 'agmc' OR ADName = 'agmc')
      AND (Commited IS NULL OR Commited = 0)
)
SELECT DISTINCT ID, num, ADName, Description_User, Description_Amex, Amount, Date
FROM t 
WHERE (t.BaseProxy = 'agmc' OR t.ADName = 'agmc') 
   AND num BETWEEN 0 AND 20
   AND (Commited IS NULL OR Commited = 0)
ORDER BY Date

修复它可能相当简单,但看到我不是SQL Server的人,我不习惯这些内部查询等。

更新:是,num用于分页。

2 个答案:

答案 0 :(得分:12)

我的近期博客文章ROW_NUMBER() being to SELECT what DENSE_RANK() is to SELECT DISTINCT似乎已经迟了两年了。您的CTE必须由此替换:

WITH t AS
(
   SELECT DISTINCT *, DENSE_RANK() OVER (ORDER BY Date, ...) AS num 
   FROM Original_Import 
   LEFT JOIN eqcas.dbo.BASE_PROXY_VIEW_WITHTARGET ON ADName = Targetuser
   WHERE (BaseProxy = 'agmc' OR ADName = 'agmc')
      AND (Commited IS NULL OR Commited = 0)
)
SELECT ...

在上面的查询中,DENSE_RANK()的{​​{1}}子句需要列出ORDER BYOriginal_Import中的所有列,以重现与BASE_PROXY_VIEW_WITH_TARGET相同的顺序{1}}关键字。这将为每个重复记录集准确分配一个排名,这样DISTINCT将再次起作用。

referenced blog post中,我还添加了SQLFiddle的链接,以更简单的方式说明这一点。

DISTINCT

An explanation why DISTINCT removes duplicate rows after window functions having been calculated can be found in this post here

答案 1 :(得分:5)

由于我无法测试甚至编译,因此对此的信心有限,但这是我所想的一般要点...

WITH t AS
(
   SELECT [insert your fields here], ROW_NUMBER() OVER (ORDER BY Date) AS num 
   FROM (
     SELECT DISTINCT *[insert your fields here]
     FROM Original_Import 
     LEFT JOIN eqcas.dbo.BASE_PROXY_VIEW_WITHTARGET ON ADName = Targetuser
     WHERE (BaseProxy = 'agmc' OR ADName = 'agmc')
      AND (Commited IS NULL OR Commited = 0)) as X
)
SELECT DISTINCT ID, num, ADName, Description_User, Description_Amex, Amount, Date
FROM t 
WHERE (t.BaseProxy = 'agmc' OR t.ADName = 'agmc') 
   AND num BETWEEN 0 AND 20
   AND (Commited IS NULL OR Commited = 0)
ORDER BY Date