取每个分区的第一行

时间:2013-01-15 14:22:20

标签: sql-server row-number

我有这个问题:

select   ROW_NUMBER() OVER ( PARTITION BY codtiers ORDER BY case when isnull(cumulapport, 0) > isnull(cumulretrait, 0) then cumulapport
 else cumulretrait
end DESC ) AS classement,
                    codTiers
           from     dbo.TiersComptesLocal 
           group by codTiers

返回此结果:

classement  |  codTiers  
-------------------------
    1       |  1XXXXX
    2       |  1XXXXX
    1       |  1YYXXX
    2       |  1YYXXX
    3       |  1YYXXX
    1       |  1XXXYY

我想显示每个分区的第一行 我希望得到这样的结果:

classement  |  codTiers  
-------------------------
    1       |  1XXXXX
    1       |  1YYXXX
    1       |  1XXXYY

任何想法都会受到欢迎。

这是我的完整查询:

select   ROW_NUMBER() OVER ( PARTITION BY tcl_codtiers ORDER BY case when isnull(cumulapport, 0) > isnull(cumulretrait, 0) then cumulapport
                                                                                                                else cumulretrait
                                                                                                           end DESC ) AS classement,

                                        TCL_CodTiers,
                                        'le montant max des ' + Senscumul + ' ( '
                        + convert(varchar(50), '') + ' € ) du tiers titulaire '
                        + TCL_CodTiers + ' ( ' + ''
                        + ' ) est supérieur au seuil fixé dans l''alerte : '
                        + '75000'

                               from     dbo.CLI_TCL_TiersComptesLocal
                                        INNER JOIN dbo.CLI_GCO_GeneriquesComptes ON TCL_CodTiers = GCO_CodTiersPrincipal
                                                                                    AND TCL_NumLien IN ( 0, 1 )
                                                                    inner join ( select TCL_CodTiers CodTiers,
                                                                sum(case when ESO_MntValoRetenuEnEuros > 0
                                                                         then ESO_MntValoRetenuEnEuros
                                                                         else 0
                                                                    end) cumulapport,
                                                                sum(case when ESO_MntValoRetenuEnEuros < 0
                                                                         then abs(ESO_MntValoRetenuEnEuros)
                                                                         else 0
                                                                    end) cumulretrait, 
                                                                      case when isnull(  sum(case when ESO_MntValoRetenuEnEuros > 0
                                                                         then ESO_MntValoRetenuEnEuros
                                                                         else 0
                                                                    end), 0) > isnull( sum(case when ESO_MntValoRetenuEnEuros < 0
                                                                         then abs(ESO_MntValoRetenuEnEuros)
                                                                         else 0
                                                                    end), 0)
                                                 then 'Apports'
                                                 else 'Retraits'
                                            end as Senscumul
                                                         from   CRO_ESO_EntreeSortie
                                                                inner join CLI_TCL_TiersComptesLocal on TCL_CodCompte = ESO_CodCompte
                                                                                                        and TCL_NumLien in ( 0, 1 )
                                                         group by TCL_CodTiers
                                                         having sum(case when ESO_MntValoRetenuEnEuros > 0
                                                                         then ESO_MntValoRetenuEnEuros
                                                                         else 0
                                                                    end) > 75000
                                                                or sum(case when ESO_MntValoRetenuEnEuros < 0
                                                                            then abs(ESO_MntValoRetenuEnEuros)
                                                                            else 0
                                                                       end) > 75000
                                                       ) surveillance on GCO_CodTiersPrincipal = CodTiers

提前致谢。

3 个答案:

答案 0 :(得分:2)

WITH CTE
AS
(
    SELECT
      ROW_NUMBER() OVER (PARTITION BY codtiers 
                         ORDER BY CASE 
                                    WHEN ISNULL(cumulapport, 0) >
                                         ISNULL(cumulretrait, 0) THEN cumulapport
                                  ELSE cumulretrait
                                  END DESC) AS classement,
                        codTiers
    FROM dbo.TiersComptesLocal 
) 
SELECT * 
FROM CTE
WHERE classement = 1;

更新

无法在同一个查询中对该列classement进行过滤,你必须使用CTE或子查询,就像在@AaronBertrand中一样。但是,如果要在同一查询中执行此操作,则必须在没有ROW_NUMBER()的情况下执行此操作:

    SELECT
      codtiers,
      MAX(CASE 
            WHEN ISNULL(cumulapport, 0) >
                 ISNULL(cumulretrait, 0) THEN cumulapport
            ELSE cumulretrait
            END DESC) AS classement
    FROM dbo.TiersComptesLocal 
    GROUP BY codtiers;

答案 1 :(得分:2)

不知道为什么你不想使用CTE,但如果你愿意,你可以使用派生表,尽管它仍然与Mahmoud已经发布的答案基本相同:

SELECT *
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY codtiers 
                                ORDER BY CASE WHEN ISNULL(cumulapport, 0)>ISNULL(cumulretrait, 0) 
                                              THEN cumulapport ELSE cumulretrait END DESC) AS classement,
             codTiers
        FROM dbo.TiersComptesLocal 
        GROUP BY codTiers) A
WHERE classement = 1

答案 2 :(得分:2)

这是一个不使用WITH的解决方案 - 虽然我不确定为什么这是一个问题。

SELECT classement, codtiers
FROM 
(
  SELECT 
    classement = ROW_NUMBER() OVER (PARTITION BY codtiers 
      ORDER BY CASE WHEN ISNULL(cumulapport, 0) > ISNULL(cumulretrait, 0) 
      THEN cumulapport ELSE cumulretrait END DESC),
    codTiers
  FROM dbo.TiersComptesLocal 
) AS x
WHERE classement = 1;