先看一段代码
   select soh1.CustomerID,soh1.SalesOrderID,soh1.OrderDate
from Sales.SalesOrderHeader soh1
where soh1.OrderDate=(
select MIN(soh2.OrderDate)
from Sales.SalesOrderHeader soh2
where soh2.CustomerID=soh1.CustomerID
)
order by CustomerID现在的问题是我想知道它在执行的时候顺序是怎么执行的?
这篇文章说了sql的执行顺序 http://www.cnblogs.com/summer_adai/archive/2011/10/28/2227605.html我现在的疑惑是当执行到where 条件时,where条件里又是一条sql语句select MIN(soh2.OrderDate)
from Sales.SalesOrderHeader soh2
where soh2.CustomerID=soh1.CustomerID
,那么它又会按照链接那篇文章所说的执行顺序执行吗?  如果按照链接的文章中的顺序执行,当执行到where条件时,它会怎么处理?跳到父查询?感觉像死循环似的 。还是遍历父查询的记录?  
望高手指点 

解决方案 »

  1.   

    SQL Select语句完整的执行顺序: 1、from子句组装来自不同数据源的数据; 
    2、where子句基于指定的条件对记录行进行筛选; 
    3、group by子句将数据划分为多个分组; 
    4、使用聚集函数进行计算; 
    5、使用having子句筛选分组; 
    6、计算所有的表达式; 
    7、使用order by对结果集进行排序。 
    另外:一个查询语句各个部分的执行顺序: 
    --8)  SELECT (9) DISTINCT (11) <TOP_specification> <select_list> 
    --(1)  FROM <left_table> 
    --(3)    <join_type> JOIN <right_table> 
    --(2)      ON <join_condition> 
    --(4)  WHERE <where_condition> 
    --(5)  GROUP BY <group_by_list> 
    --(6)  WITH {CUBE | ROLLUP} 
    --(7)  HAVING <having_condition> 
    --(10) ORDER BY <order_by_list> 
      

  2.   


    他执行的时候会没一个id去一个最小的,这样一直到所有id的最小的取完为止
      

  3.   

    改为这样,会不会效率高很多:
    select soh1.CustomerID,soh1.SalesOrderID,soh1.OrderDate
    from Sales.SalesOrderHeader soh1
    left join (
    select soh2.CustomerID fid,MIN(soh2.OrderDate) fod
    from Sales.SalesOrderHeader soh2
    group by soh2.CustomerID
    ) b on soh1.CustomerID=b.fid and soh1.OrderDate=b.fod
    where b.fid is not null
    order by CustomerID
      

  4.   


    select CustomerID,SalesOrderID,OrderDate from(
    select row_number()over(partition by customerid 
    order by OrderDate asc) as nun,* from Sales.SalesOrderHeader)a
    where num=1--2005以上版本使用row_number(),效率不低
      

  5.   

    row_number()over是个好东西啊
    否则,按customerid取OrderDate 第2大的,sql麻烦死了(最大、最小还有max、min,第2、第3的就不行了)另外,sql只有数值的sum,一直缺少字符串的“sum”
    不分组直接sum字符串还好办:select @s=@s+fstring+',',
    如果要分组,这个办法也不行了
    不知道有没有好的语法来解决
      

  6.   

    她先按照正常步骤走,到了where soh1.OrderDate=(
        select MIN(soh2.OrderDate)
            from Sales.SalesOrderHeader soh2
            where soh2.CustomerID=soh1.CustomerID
    ) 这个步骤再按照每个ID去一个最小的DATE,一直到所有ID都取完结束,其它步骤是一样的啊你看我给你的语句完整的执行顺序
      

  7.   

    我说一下我的理解 :  父查询会把from的数据源组装到 VT1 然后运用where条件进行筛选,但在 子查询里又是一个查询, 然后from的数据源假设 组装到VT2,然后运用子查询的Where条件进行筛选,现在它会从父查询中一条一条遍历,比如父查询有下面的数据:
    1 43860 2001-08-01 00:00:00.000
    1 44501 2001-11-01 00:00:00.000
    1 45283 2002-02-01 00:00:00.000
    1 46042 2002-05-01 00:00:00.000
    2 46976 2002-08-01 00:00:00.000
    2 47997 2002-11-01 00:00:00.000
    2 49054 2003-02-01 00:00:00.000
    2 50216 2003-05-01 00:00:00.000
    2 51728 2003-08-01 00:00:00.000
    2 57044 2003-11-01 00:00:00.000
    第一条CustomerID 是1 ,然后子VT2 的where条件运用CustomerID=1的条件进行筛选,得到customerID为1的最小Orderdate,然后继续遍历VT1 的下一条,还是CustomerID 是1,得到customerID为1的最小Orderdate...一直到结束。 这时候返回到VT1 的where筛选条件,变成where Orderdate=(
     所有minOrderdate的集合,还有重复值,比如CustomerID 为1的用户就有4条MinOrderDate值)
    然后才得到结果?
      

  8.   

    是的,你这个查询不能排除重复的情况,可以使用row_number()over,这个来得快,而且效率你较高,最重要的是能够只取一个最小的date
      

  9.   

    上面的理解不对,where条件不能运用到集合...
      

  10.   


    后面的主查询加一个top 1,就只有1行了,就可以=了
      

  11.   

    执行的顺序:
    表SalesOrderHeader和表SalesOrderHeader先执行笛卡尔积,也就是自身交叉连接。
    然后执行过滤条件:
    where soh2.CustomerID=soh1.CustomerID
    where soh1.OrderDate=(
    这两个应该是同时执行。求验证。,这的时候,我个人认为,在物理逻辑处理的时候,应该和inner join一样,或LEFT join 一样。
    存储引擎会自己选择最优的路径。最后执行:order by 
      

  12.   

    我不是要结果呀, 我是想理解这个过程..
    比如又来一个查询 :
    SELECT sc.AccountNumber,
            (select Min(OrderDate)
                from Sales.SalesOrderHeader soh
                where soh.CustomerID=sc.CustomerID
            )AS OrderDate
    From Sales.Customer sc;
    然后我还是不能理解......
      

  13.   


    然后我也不理解了,干嘛非得在这样一个问题是纠结,row_number()over好用多了