3

Is there any way where I can avoid the inner join to get the customer firstname, and lastname from customer table and how can i optimize the execution plan?

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

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
Registered User
  • 1,554
  • 3
  • 22
  • 37
  • Why do you think INNER JOIN is a bad thing? This query is better then grouping by firstname, lastname. COUNT() OVER() should be roughly as good as your one. I'd do Customer LEFT JOIN (select CustomerID, count(*) cnt from SalesInvoice GROUP BY CustomerID) if your purpose is brevity. – Alsin Mar 25 '13 at 08:48

3 Answers3

2

There could be 2 ways to do it. One way is to include all non-aggregate columns into the group by list as below:

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

Another way to do it, would be to use an aggregate function (min or max should do) in the select list:

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

I think the first query may be better in performance. To improve overall performance you will need to create an included or covering index.

You can have a look at the following links to give you an idea on included indexes:

  1. Why use the INCLUDE clause when creating an index?
  2. http://msdn.microsoft.com/en-IN/library/ms190806.aspx
Community
  • 1
  • 1
nikhil pinto
  • 331
  • 1
  • 4
  • 15
1

Try this option with OVER() clause

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

For improving performance you need this index

CREATE INDEX ix_Customerid_Customer ON Customer(Customerid) INCLUDE(firstname, lastname)
Aleksandr Fedorenko
  • 16,594
  • 6
  • 37
  • 44
0

Try that one:

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
MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263