先看一段代码
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条件时,它会怎么处理?跳到父查询?感觉像死循环似的 。还是遍历父查询的记录?
望高手指点
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条件时,它会怎么处理?跳到父查询?感觉像死循环似的 。还是遍历父查询的记录?
望高手指点
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>
他执行的时候会没一个id去一个最小的,这样一直到所有id的最小的取完为止
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
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(),效率不低
否则,按customerid取OrderDate 第2大的,sql麻烦死了(最大、最小还有max、min,第2、第3的就不行了)另外,sql只有数值的sum,一直缺少字符串的“sum”
不分组直接sum字符串还好办:select @s=@s+fstring+',',
如果要分组,这个办法也不行了
不知道有没有好的语法来解决
select MIN(soh2.OrderDate)
from Sales.SalesOrderHeader soh2
where soh2.CustomerID=soh1.CustomerID
) 这个步骤再按照每个ID去一个最小的DATE,一直到所有ID都取完结束,其它步骤是一样的啊你看我给你的语句完整的执行顺序
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值)
然后才得到结果?
后面的主查询加一个top 1,就只有1行了,就可以=了
表SalesOrderHeader和表SalesOrderHeader先执行笛卡尔积,也就是自身交叉连接。
然后执行过滤条件:
where soh2.CustomerID=soh1.CustomerID
where soh1.OrderDate=(
这两个应该是同时执行。求验证。,这的时候,我个人认为,在物理逻辑处理的时候,应该和inner join一样,或LEFT join 一样。
存储引擎会自己选择最优的路径。最后执行:order by
比如又来一个查询 :
SELECT sc.AccountNumber,
(select Min(OrderDate)
from Sales.SalesOrderHeader soh
where soh.CustomerID=sc.CustomerID
)AS OrderDate
From Sales.Customer sc;
然后我还是不能理解......
然后我也不理解了,干嘛非得在这样一个问题是纠结,row_number()over好用多了