代码之家  ›  专栏  ›  技术社区  ›  Registered User

如何避免额外的内部联接来优化此查询?

  •  3
  • Registered User  · 技术社区  · 11 年前

    有没有什么方法可以避免内部联接以从customer表中获取customer firstname和lastname,以及如何优化执行计划?

    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
    

    enter image description here

    3 回复  |  直到 11 年前
        1
  •  2
  •   Community CDub    7 年前

    有两种方法可以做到这一点。 一种方法是将所有非聚合列按列表包括到组中,如下所示:

    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
    

    另一种方法是在选择列表中使用聚合函数(min或max should do):

    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
    

    我认为第一个查询的性能可能会更好。为了提高整体性能,您需要创建一个包含索引或覆盖索引。

    您可以查看以下链接,了解包含索引:

    1. Why use the INCLUDE clause when creating an index?
    2. http://msdn.microsoft.com/en-IN/library/ms190806.aspx
        2
  •  1
  •   Oleksandr Fedorenko    11 年前

    使用尝试此选项 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)
    
        3
  •  0
  •   MarcinJuraszek    11 年前

    试试这个:

    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