SELECT * FROM TABLE
FROMWHEREGROUP BYHAVINGSELECTORDER BY比如我们要查询筛选客户71下的订单,我们会进行如下查询。
SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numbers FROM Sales.OrdersWHERE custid = "71"GROUP BY empid, YEAR(orderdate)HAVING COUNT(*) > 1ORDER BY empid, orderyear但是实际上按照我们上述所说的顺序,其逻辑化的子句是这样的。
FROM Sales.OrdersWHERE custid = 71GROUP BY empid, YEAR(orderdate)HAVING COUNT(*) > 1SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numberordersORDER BY empid, orderyear对于博主的SQL系列并非会将SELECT、HAVING等语句单独拿来讲,针对的是有了一定基础的人群,后续内容也是如此,所以到了这里我们算是将简单查询语句叙述完毕。但是我一直强调的是简短的内容,深入的理解,所以接下来看看有些需要注意的地方。
查询方式一(整表查询)
USE TSQL2012GOIF EXISTS(SELECT 1FROM Sales.Orders)SELECT "SELECT 1"GOIF EXISTS(SELECT *FROM Sales.Orders)SELECT "SELECT *"GO此时查看执行计划是相同的,如下:
查询方式二(在索引列上条件查找)
我们对某一列创建索引
CREATE INDEX ix_shipnameON Sales.Orders(shipname)接下来继续查看其执行计划。
此时显示查询计划依然一样。我们再来看看其他查询方式。
查询方式三(使用聚合函数)
USE TSQL2012GOIF (SELECT 1FROM Sales.OrdersWHERE shipname = "Ship to 85-B") = 1SELECT "SELECT 1"GOIF (SELECT COUNT(*)FROM Sales.OrdersWHERE shipname = "Ship to 85-B") = 1SELECT "SELECT *"GO我们看到查询计划依然一样。
查询方式四(使用聚合函数Count在非索引列上查找)
USE TSQL2012GOIF (SELECT COUNT(1)FROM Sales.OrdersWHERE freight = "41.3400") = 1SELECT "SELECT 1"GOIF (SELECT COUNT(*)FROM Sales.OrdersWHERE freight = "41.3400") = 1SELECT "SELECT *"GO我们看到执行计划还是一样。
查询方式五(子查询)
我们看看在子查询中二者性能如何
USE TSQL2012SELECT custid, companyname FROM Sales.Customers AS CWHERE country = N"USA" ANDEXISTS (SELECT * FROM Sales.Orders AS O WHERE O.custid = C.custid)GOSELECT custid, companyname FROM Sales.Customers AS CWHERE country = N"USA" ANDEXISTS (SELECT 1 FROM Sales.Orders AS O WHERE O.custid = C.custid)此时结果二者查看执行计划还是一样
查询方式六(在视图中查询)
我们创建视图继续来比较SELECT 1和SELECT *的性能
USE TSQL2012GoCREATE VIEW SaleOdersViewASSELECT shipaddress,shipname,(SELECT unitprice FROM Sales.OrderDetails AS sod where sod.orderid = so.orderid) as tc3FROM Sales.Orders AS soGO进行视图查询
USE TSQL2012SELECT 1 FROM dbo.SaleOdersViewgoSELECT * FROM dbo.SaleOdersViewgo结果执行计划如下:
此时我们通过上述图发现利用视图查询时,SELECT *的性能是如此低下占有97%,而SELECT 1才3%,这是为何呢?不明白其中原因,希望有清楚其中原因的园友能够留下你们的评论给出合理的解释。
SELECT 所有列和SELECT *性能探讨
一直以来所有教程都在讲SELECT *性能比SELECT 所有列性能低,同时也给出了合理的理由,我也一直这样认为,但是在查资料学习过程中,发现如下一段话。
I don"t think there is any difference, as long as the SELECT 1/* is inside EXISTS, which really doesn"t return any rows – it just returns boolean as soon as condition of the WHERE is checked.I"m quite sure that the SQL Server Query Optimizer is smart enough not to search for the unneeded meta data in the case of EXISTS.I agree that in all the other situations SELECT * shouldn"t be used for the reasons Simon mentioned. Also, index usage wouldn"t be optimal etc.For me EXISTS (SELECT * ..) is the only place where I allow myself to write SELECT * in production code ;)最后一句表明SELECT *使用的唯一场景是在EXISTS中,看到这里颠覆我以往看的教程的想法,不太明确,真的是这样吗?