我怎样才能避免额外的内部连接来优化这个查询?

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

【讨论】:

以上是关于我怎样才能避免额外的内部连接来优化这个查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何避免相对布局中可绘制背景的额外高度?

逻辑读取数量随着一个额外的内部连接而爆炸

SQL语句优化

SQL - 避免额外的 GROUP BY(并提高查询性能)

Stylus:当一个元素有一个额外的类时,我怎样才能改变它的颜色?

如何避免在 Relay.createcontainer 内置的 graphql 查询中添加额外的字段?