TSQL CTE(常见的表表达式)错误

时间:2017-06-01 12:48:02

标签: sql sql-server tsql common-table-expression row-number

我正在使用Microsoft SQL Server 2008(SP3) - 10.0.5520.0(X64)     Windows NT 6.0(Build 6002:Service Pack 2)上的标准版(64位)

说明

  1. [ORC_RESULT]GROUPING_SELECTCTE表。
  2. 我对CTE(公用表表达式)有一个奇怪的错误。

    SELECT a.keysbor
    --,gs.[rank]
    FROM [ORC_RESULT] AS a inner JOIN GROUPING_SELECT AS gs
        ON a.keysbor = gs.keysbor
    WHERE gs.[RANK] = 1
    ORDER BY a.keysbor
    

    结果36行(没有重复的行)

    SELECT a.keysbor
    ,gs.[rank]
    FROM [ORC_RESULT] AS a inner JOIN GROUPING_SELECT AS gs
        ON a.keysbor = gs.keysbor
    WHERE gs.[RANK] = 1 
    ORDER BY a.keysbor
    

    结果29行

    问:为什么过滤器gs.[RANK] = 1仅在gs.[rank]声明中存在字段SELECT时才适用?

    without gs.[rank]   with gs.[rank]  rank
    10072002992443  10072002992443       1
    10072002992444  10072002992444       1
    10072002992445  10072002992445       1
    10072002992446  10072002992446       1
    10072002992447  10072002992447       1
    10072002992448  10072002992448       1
    10072002992449  10072002992449       1
    10072002992450  10072002992450       1
    10072002992451  10072002992451       1
    10072002992452  10072002992452       1
    10072002992453  10072002992453       1
    10072002992454  10072002992454       1
    10072002992455  10072002992455       1
    10072002992456  10072002992456       1
    10072002992457  10072002992457       1
    10072002992458  10072002992458       1
    10072002992459  10072002992459       1
    10072002992460  10072002992460       1
    10072002992461                       2
    10072002992462                       2
    10072002992463                       2
    10072002992464                       2
    10072002992465                       2
    10072002992466                       2
    10072002992467                       2
    10072002992736  10072002992736       1
    10072002992866  10072002992866       1
    10072002992867  10072002992867       1
    10072002992868  10072002992868       1
    10072002992869  10072002992869       1
    10072002992870  10072002992870       1
    10072002992871  10072002992871       1
    10072002992872  10072002992872       1
    10072002992873  10072002992873       1
    10072002992874  10072002992874       1
    10072002992875  10072002992875       1
    

1 个答案:

答案 0 :(得分:1)

我认为你的[等级]不是以确定的方式计算的,即

PARTITION BY A.[KEYKRT], A.[VIDSBR],A.[ORC_ID_ED] ORDER BY A.[ORC_ID_ED] 

不能单独确定顺序,因此根据计划运算符,row_number()可以为不同的行分配1。 我举一个例子,计划是相同的,但行的顺序是不同的,使用相同的输入数据,你会得到2个不同的结果。 根据您在SELECT中放置的列,优化程序构建不同的计划,并且您的RANK在不同的行中对应于1(对应于不同的keysbor),因此在连接keysbor时,将返回不同的行数。 因此,在这两种情况下都应用了过滤器等级= 1,但是将1分配给不同的行。

以下是示例:

    declare @t table( a int, b int, c int, primary key(c desc, b)); /*run it as it is, then uncomment PK and run again*/
    insert into @t values 
    (1,1,1), (1,1,2), (1,1,3),
    (1,2,1), (1,2,2), (1,2,3);

    declare @t1 table( c int);
    insert @t1 values (1);

    with cte as (
    select row_number() over (partition by a, b order by b) as rn,
           a,
           b,
           c
    from @t 
    group by a, b, c
    )

    select *
    from cte c join @t1 t on c.c = t.c
    where rn = 1;

正如你所看到的,我总是有相同的输入,但在第一种情况下,我没有声明主键,而在第二种情况下我没有。 返回的行不同,但并不意味着过滤器不起作用,它只是意味着在第一种情况下rn = 1归因于2行c = 1,但在第二种情况下rn = 1有两行c = 1且c = 3.