数据库:T-SQL查询语句的执行步骤
来源:优易学  2011-9-21 17:13:24   【优易学:中国教育考试门户网】   资料下载   IT书店

  T-SQL是需要优化的。而优化的前提是你对它的执行步骤有清楚的认识。我经常去给讲课或者咨询辅导的时候,就发现很多朋友对此了解甚少。下面截取了我的一个PPT,给大家参考一下
  下面这个脚本可以解释这个过程
  /*
  这个脚本用来帮助用户理解T-SQL查询的逻辑顺序和原理。
  作者:陈希章
  */
  /*
  准备数据架构和数据
  */
  SET NOCOUNT ON;
  USE tempdb;
  GO
  IF OBJECT_ID('dbo.Orders') IS NOT NULL
  DROP TABLE dbo.Orders;
  GO
  IF OBJECT_ID('dbo.Customers') IS NOT NULL
  DROP TABLE dbo.Customers;
  GO
  CREATE TABLE dbo.Customers
  (
  customerid  CHAR(5)     NOT NULL PRIMARY KEY,
  city        VARCHAR(10) NOT NULL
  );
  INSERT INTO dbo.Customers(customerid, city) VALUES('FISSA', 'Madrid');
  INSERT INTO dbo.Customers(customerid, city) VALUES('FRNDO', 'Madrid');
  INSERT INTO dbo.Customers(customerid, city) VALUES('KRLOS', 'Madrid');
  INSERT INTO dbo.Customers(customerid, city) VALUES('MRPHS', 'Zion');
  CREATE TABLE dbo.Orders
  (
  orderid    INT        NOT NULL PRIMARY KEY,
  customerid CHAR(5)    NULL     REFERENCES Customers(customerid)
  );
  INSERT INTO dbo.Orders(orderid, customerid) VALUES(1, 'FRNDO');
  INSERT INTO dbo.Orders(orderid, customerid) VALUES(2, 'FRNDO');
  INSERT INTO dbo.Orders(orderid, customerid) VALUES(3, 'KRLOS');
  INSERT INTO dbo.Orders(orderid, customerid) VALUES(4, 'KRLOS');
  INSERT INTO dbo.Orders(orderid, customerid) VALUES(5, 'KRLOS');
  INSERT INTO dbo.Orders(orderid, customerid) VALUES(6, 'MRPHS');
  INSERT INTO dbo.Orders(orderid, customerid) VALUES(7, NULL);
  /*
  一个测试查询,检索那些订单个数小于3的客户,并且按订单总数排序(升序)
  */

  SELECT C.customerid, COUNT(O.orderid) AS numorders
  FROM dbo.Customers AS C
  LEFT OUTER JOIN dbo.Orders AS O
  ON C.customerid = O.customerid
  WHERE C.city = 'Madrid'
  GROUP BY C.customerid
  HAVING COUNT(O.orderid) < 3
  ORDER BY numorders;
  /*第一步:处理FROM子句,把来源的表进行CROSS JOIN(笛卡尔乘积)
  我这里把结果做一个生成表查询,写到一个临时表(VT1)中去
  */
  SELECT C.customerid as Customer,c.city,o.*  INTO #VT1 FROM dbo.Customers C,dbo.Orders  O
  SELECT * FROM #VT1
  --返回28行数据(4*7)
  --第二步:处理ON子句,只把那些两个表的customerid匹配的行找出来,我把它们放到VT2中去
  SELECT temp.* INTO #VT2 FROM (SELECT * FROM #VT1 WHERE Customer=customerid) temp
  SELECT * FROM #VT2
  --返回6行数据
  --第三步:根据JOIN语句的类型,决定是否要添加行到VT2中去,例如如果是LEFT  JOIN的话,那么就要检查坐边的表(我们这里是customers表)的连接键值是否都存在,如果不存在就要去添加到VT2中
  SELECT temp.* INTO #VT3 FROM
  (SELECT * FROM #VT2
  UNION ALL
  SELECT CustomerID,City,NULL,NULL FROM dbo.Customers c WHERE NOT EXISTS(SELECT DISTINCT Customer FROM #VT2 WHERE Customer=c.CustomerID)) temp
  SELECT * FROM #VT3
  --返回7行数据,其中有一个客户,因为没有订单,这一步中被添加进来。它的Orders的记录被标记为NULL
  --第四步:处理WHERE 子句,对VT3的结果集进行过滤,我们的条件是city=Madid
  SELECT temp.* INTO #VT4 FROM
  (SELECT * FROM #VT3 WHERE city='Madrid') temp
  SELECT * FROM #VT4
  --返回6行数据,因为有一个客户不是这个城市的
  --第五步:处理GROUP子句,进行分类汇总
  SELECT temp.* INTO #VT5 FROM
  (SELECT Customer,COUNT(OrderID)  as orderidcount,COUNT(city) as citycount,Count(customerid)  as customeridcount FROM #VT4 GROUP BY Customer) temp
  SELECT * FROM #VT5
  --返回3行数据,根据客户分组,统计了订单的个数
  --这里会不会去统计其他列的汇总呢
  --因为没有WITH Rollup和WITH Cube语句,所以跳过第六步,进入HAVING子句的处理
  --第六步:处理HAVING子句,对GROUP之后的结果进行筛选,我们这里的条件是orderidcount<3
  SELECT temp.* INTO #VT6 FROM
  (SELECT * FROM #VT5 WHERE orderidcount<3) temp
  SELECT * FROM #VT6
  --返回2行数据
  --第七步:使用SELECT 的字段列表过滤结果集
  SELECT #VT6.Customer,#VT6.orderidcount as  numorders  INTO #VT7 FROM #VT6
  SELECT * FROM #VT7
  --还是2行数据,只不过只有两个列了
  --第八步:跳过DISTINCT,进行OrderBy操作
  SELECT #VT7.* INTO #VT8 FROM #VT7 Order By #VT7.Customer
  SELECT * FROM #VT8
  --返回2行数据,经过排序
  --这个查询结束演示。完整的8个步骤

责任编辑:小草

文章搜索:
 相关文章
热点资讯
热门课程培训