DECLARE @TB TABLE (id INT,name NVARCHAR(10))
INSERT @TB
SELECT 1 ,'jack' UNION ALL
SELECT 2 ,'sam' UNION ALL
SELECT 6 ,'micle' UNION ALL
SELECT 7 ,'Jop' UNION ALL
SELECT 7 ,'Jop' UNION ALL
SELECT 12, 'Nill' 
declare @s varchar(50)
set @s=''SELECT  @S=@S+NAME  FROM @TB 
SELECT @SSET @S=''SELECT  DISTINCT @S=@S+NAME  FROM @TB 
SELECT @SSET @S=''SELECT  DISTINCT @S=NAME  FROM @TB 
SELECT @S
/*(所影响的行数为 6 行)                                                   
-------------------------------------------------- 
jacksammicleJopJopNill(所影响的行数为 1 行)                                                   
-------------------------------------------------- 
sam(所影响的行数为 1 行)                                                   
-------------------------------------------------- 
sam(所影响的行数为 1 行)*/
DISTINCT为变量赋值的顺序是如何的呢?每次都会覆盖前面的值??

解决方案 »

  1.   

    小F理解下,为什么加了DISINTC之后,只能是最后一条了呢
      

  2.   

    我是看执行顺序 是先select 然后distinct
      

  3.   

    ---这样好理解些
    DECLARE @TB TABLE (id INT,name NVARCHAR(10))
    INSERT @TB
    SELECT 1 ,'jack' UNION ALL
    SELECT 2 ,'sam' UNION ALL
    SELECT 6 ,'micle' UNION ALL
    SELECT 7 ,'Jop' UNION ALL
    SELECT 7 ,'Jop' UNION ALL
    SELECT 12, 'Nill' 
    declare @s varchar(50)
    set @s=''SELECT  @S=@S+NAME  FROM @TB 
    SELECT @SSET @S='a'SELECT  DISTINCT @S=@S+NAME  FROM @TB 
    SELECT @SSET @S='a'SELECT  DISTINCT @S=NAME  FROM @TB 
    SELECT @S/*
    (6 行受影响)--------------------------------------------------
    jacksammicleJopJopNill(1 行受影响)
    --------------------------------------------------
    asam(1 行受影响)
    --------------------------------------------------
    sam(1 行受影响)*/
      

  4.   

    ---去体会下执行的顺序
    DECLARE @TB TABLE (id INT,name NVARCHAR(10))
    INSERT @TB
    SELECT 1 ,'jack' UNION ALL
    SELECT 2 ,'sam' UNION ALL
    SELECT 6 ,'micle' UNION ALL
    SELECT 7 ,'Jop' UNION ALL
    SELECT 7 ,'Jop' UNION ALL
    SELECT 12, 'Nill' 
    declare @s varchar(50)
    set @s='a'SELECT  @S=@S+NAME  FROM @TB 
    SELECT @SSET @S='a'SELECT  DISTINCT @S=@S+NAME  FROM @TB 
    SELECT @SSET @S='a'SELECT  DISTINCT @S=NAME  FROM @TB 
    SELECT @S/*(6 行受影响)--------------------------------------------------
    ajacksammicleJopJopNill(1 行受影响)
    --------------------------------------------------
    asam(1 行受影响)
    --------------------------------------------------
    sam(1 行受影响)
    */
      

  5.   

    哈哈 xiaoF这回答不是从那个帖子copy过来的吧
      

  6.   

    小F,这个我理解了,
    SET @S='a'SELECT  DISTINCT @S=@S+NAME  FROM @TB 
    SELECT @SSET @S='a'SELECT  DISTINCT @S=NAME  FROM @TB 
    SELECT @S
    就这两句的结果,第一句显然没累加,好像每次执行完后,@S又返回原值,最后才会得到那样的结果,
    第二句很好理解,被覆盖了,
      

  7.   

    看看执行计划就清楚了。
    SELECT  @S=@S+NAME  FROM @TB 
    不需要排序,可以理解为循环读取表中的每一行,和@s进行加运算SELECT  DISTINCT @S=@S+NAME  FROM @TB  
    需要一个distinct排序,默认按照升序进行排序,那么取得是最后一个值,所以得到的结果是 sam,最后一个也是如此
      

  8.   

    老师意思是,加了DISTINCT 后,没有循环读取了?
      

  9.   

    第一个很好理解,循环读取累加,可是加了DISTINCT它会排序,影响了累加?
      

  10.   

    可能是跟指针一样 
    排序以后指针已经指向了最后一行 而不加distinct的时候是从第一行读取到最后一行的同时在循环读取累加
      

  11.   

    首先解释第三个:
    SELECT  DISTINCT @S=NAME  FROM @TB 
    SELECT @S
    这个好容易理解吧, 仅是因为列的输出取决于应用 DISTINCT 的列排序规则,记录里S的排在最后,所以@S里存的是最后一个列的输出也就是SAM
      

  12.   

    第二句,我先写一个SQLselect 
        distinct 
        @s = t
    from 
        (select @s+name as t from @tb) as  b二次标量计算其实是这个过程,好,看到这儿,你再在第三个SQL的基础上来理解 一下这个SQL
    我瞎想的
      

  13.   

    呵呵,distinct排序与取最后一个值这个行为无关
      

  14.   

    或是这样,因为@s最初始''就是这样,
    SELECT  DISTINCT @S=''+NAME  FROM @TB 
    SELECT @S 
    ==>SELECT @S= ''+NAME  FROM @TB  order by name 
    SELECT @S
      

  15.   

    我是这样理解的,不知道对不对第一个查询没有排序,所以是以物理顺序来相加的
    第二和第三个查询,由于使用了DISTINCT,另外使用了变量,所以相当于distinct top 1,这样就会取排序后的最后一条数据,所以取到了sam
      

  16.   

    结果形同,但是事实没有top
    不要被变量给蒙了呀,你可以把变量搞成常量或去了
      

  17.   

    根据石头哥讲的试了一下,这样写就明白多了,DISTINCT是根据
    @s+S

    CASE WHEN S='D' THEN 'F'+S ELSE @s+S END
    来进行排序的。
    排序完成后进行@S=...的操作,这样@S最后得到的是排序结果的最后一条。
    DECLARE @T TABLE (S VARCHAR(50))
    INSERT INTO @T
    SELECT 'A' UNION ALL
    SELECT 'B' UNION ALL
    SELECT 'C' UNION ALL
    SELECT 'E' UNION ALL
    SELECT 'D'
    DECLARE @S VARCHAR(100)SELECT @S=''
    SELECT DISTINCT @S= @s+S  FROM @TSELECT @S
    --E
    SELECT @S=''
    SELECT DISTINCT @S=CASE WHEN S='D' THEN 'F'+S ELSE @s+S END  FROM @TSELECT @S
    --FS
      

  18.   

    额..sqlserver的语法解析真是高深难测....不知道为什么加了distinct会让select语法编译出现如此大的变化?
      

  19.   

    石头大哥,越想越闷了,那么
    select 
        
        @s = t 
    from 
        (select @s+name as t from @tb) as  b 
    先赋值@S+NAME,最后再赋值给@S的话,应该是不排序的最后一个呀?
    SELECT @S=NAME FROM @TB
    类似这种了
      

  20.   

    DECLARE @TB TABLE (id INT,name NVARCHAR(10))
    INSERT @TB
    SELECT 1 ,'jack' UNION ALL
    SELECT 2 ,'sam' UNION ALL
    SELECT 6 ,'micle' UNION ALL
    SELECT 7 ,'Jop' UNION ALL
    SELECT 7 ,'Jop' UNION ALL
    SELECT 12, 'Nill' 
    declare @s varchar(50)
    set @s=''
     SELECT  DISTINCT @S=@S+NAME  FROM @TB 
    SELECT @S
    重点看这个sql的执行情况,其它两个很好理解;此sql的实际执行文本为(set SHOWPLAN_TEXT on)
    ------------------------------------------------------------------------------------------------
      |--Compute Scalar(DEFINE:([Expr1005]=CONVERT_IMPLICIT(varchar(50),[Expr1004],0)))
           |--Sort(DISTINCT ORDER BY:([Expr1004] ASC))
                |--Compute Scalar(DEFINE:([Expr1004]=CONVERT_IMPLICIT(nvarchar(50),[@s],0)+[name]))
                     |--Table Scan(OBJECT:(@TB))   
    这个执行顺序是select @s+name from @tb(这里的@s='',这里没有赋值,而且@s并没有保存name的值,只是做了一个"+"运算,执行完的结果其它就是原表@tb的结果,下两步就是排序和循环赋值)----->排序--->再把最后一个值赋值给@s
      

  21.   

    是因为distinct是select后再排序,所以最后出来的还是最后一个
      

  22.   

    石头大哥,这个我看懂了,就是DISTINCT后会排序,这个我理解了,呵呵,
      

  23.   

    楼主我明白了
    原来对变量进行排序都会有这个情况
    比如
    DECLARE @TB TABLE (id INT,name NVARCHAR(10))
    INSERT @TB
    SELECT 1 ,'jack' UNION ALL
    SELECT 2 ,'sam' UNION ALL
    SELECT 6 ,'micle' UNION ALL
    SELECT 7 ,'Jop' UNION ALL
    SELECT 7 ,'Jop' UNION ALL
    SELECT 12, 'Nill' 
    declare @s varchar(50)
    set @s=''SELECT  @S=@S+NAME  FROM @TB order by @s+name
    select @s
    ---------------
    samdistinct有一个步骤就是对等号右边的值进行排序,而order by语句实际上就是如石头老大所说是先做一个套查询然后排序,而作嵌套查询的时候@s还是''
      

  24.   

    呵呵,理解了,这个看执行计划,
    先计算,
    再有个DISTINCT ORDER BY 排序,是按@S+NAME排的
    再计算,
    最后查询出结果!