我怎样才能避免额外的内部连接来优化这个查询?
Posted
技术标签:
【中文标题】我怎样才能避免额外的内部连接来优化这个查询?【英文标题】:How can i avoid an extra inner join to optimize this query? 【发布时间】:2013-03-14 15:52:47 【问题描述】:有什么方法可以避免内部连接以从客户表中获取客户名字和姓氏,以及如何优化执行计划?
SELECT c1.firstname, c1.lastname, t.*
FROM customer c1
INNER JOIN
(select c.Customerid ,count(si.CustomerID) as 'No Of Orders'
from Customer c
LEFT OUTER join SalesInvoice si ON si.CustomerID = c.CustomerID
GROUP by c.CustomerID) as t
ON c1.CustomerID = t.Customerid
【问题讨论】:
为什么你认为 INNER JOIN 是一件坏事?此查询比按名字、姓氏分组更好。 COUNT() OVER() 应该和你的一样好。如果您的目的是简洁,我会做 Customer LEFT JOIN (select CustomerID, count(*) cnt from SalesInvoice GROUP BY CustomerID)。 【参考方案1】:试试那个:
SELECT
c.firstname,
c.lastname,
c.CustomerId,
count(si.CustomerID) as 'No Of Orders'
FROM
customer c
LEFT OUTER JOIN
SalesInvoice si ON si.CustomerID = c.CustomerID
GROUP BY
c.CustomerID,
c.firstname,
c.lastname
【讨论】:
【参考方案2】:用OVER() 子句试试这个选项
SELECT c1.Customerid, c1.firstname, c1.lastname,
COUNT(si.CustomerID) OVER(PARTITION BY c1.CustomerID) AS 'No Of Orders'
FROM customer c1 LEFT JOIN SalesInvoice si ON si.CustomerID = c1.CustomerID
为了提高性能,你需要这个索引
CREATE INDEX ix_Customerid_Customer ON Customer(Customerid) INCLUDE(firstname, lastname)
【讨论】:
这将重复 customerid, firstname @Vishwanath Dalvi 在示例中 OP 客户 ID,名字也重复;)【参考方案3】:可能有两种方法可以做到这一点。 一种方法是将所有非聚合列包含到 group by 列表中,如下所示:
SELECT
c.firstname,
c.lastname,
c.CustomerId,
count(si.CustomerID) as 'No Of Orders'
FROM
customer c
LEFT OUTER JOIN
SalesInvoice si ON si.CustomerID = c.CustomerID
GROUP BY
c.CustomerID,
c.firstname,
c.lastname
另一种方法是在选择列表中使用聚合函数(应该使用最小值或最大值):
SELECT
MIN(c.firstname) as firstname,
MIN(c.lastname) as lastname,
c.CustomerId,
count(si.CustomerID) as 'No Of Orders'
FROM
customer c
LEFT OUTER JOIN
SalesInvoice si ON si.CustomerID = c.CustomerID
GROUP BY
c.CustomerID
我认为第一个查询的性能可能会更好。为了提高整体性能,您需要创建一个包含或覆盖索引。
您可以查看以下链接,了解包含的索引:
-
Why use the INCLUDE clause when creating an index?
http://msdn.microsoft.com/en-IN/library/ms190806.aspx
【讨论】:
以上是关于我怎样才能避免额外的内部连接来优化这个查询?的主要内容,如果未能解决你的问题,请参考以下文章