Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
kpgraci
Yak Posting Veteran
68 Posts |
Posted - 2012-06-15 : 11:00:11
|
I want to add a count field to an existing query. Basically I want to return the number of child records associated with a parent record, like how many invoices does a customer have.I will show my actual query later, but here is a simple query showing what I think needs to be done.Sample query without COUNT:SELECT * FROM Customers c WHERE c.ID=@custIdSample query with COUNT added:SELECT c.*, COUNT(a.Id) AS InvoiceCountFROM Customers c, INvoice aWHERE c.ID=@custId AND a.CustId=c.IdQuestion 1: Will this work?If not, what is the correct way to do this?If it is correct, then why does the same technique not work on my more complex query below?Actual query without COUNT: (this works)SELECT TOP 50p.PolicyNumber,FormLOB.LOB AS xLOB,comp.Name AS xCompanyName,prod.Name AS xCSR,c.Name AS xClientNameFROM Policies p LEFT JOIN FormLOB ON p.LOB = FormLOB.ID LEFT JOIN Clients comp ON comp.ID=p.CompanyID LEFT JOIN Clients prod ON prod.ID=p.CSR LEFT JOIN Clients c ON c.ID=p.ClientIDWHERE p.SN = @SN ORDER BY p.ModifiedOn DESCActual query with COUNT added: (this fails)SELECT TOP 50p.PolicyNumber,FormLOB.LOB AS xLOB,comp.Name AS xCompanyName,prod.Name AS xCSR,c.Name AS xClientName,COUNT(act.ID) ax xActivityCountFROM Policies p LEFT JOIN FormLOB ON p.LOB = FormLOB.ID LEFT JOIN Clients comp ON comp.ID=p.CompanyID LEFT JOIN Clients prod ON prod.ID=p.CSR LEFT JOIN Clients c ON c.ID=p.ClientIDLEFT JOIN PolicyActivity act ON act.PolicyID=p.IDWHERE p.SN = @SN ORDER BY p.ModifiedOn DESCThe error returned is:Exception:Column 'Policies.ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.which seems pretty specific but I don't know what it's trying to tell me.kpg |
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2012-06-15 : 11:11:33
|
quote: SELECT c.*, COUNT(a.Id) AS InvoiceCountFROM Customers c, INvoice aWHERE c.ID=@custId AND a.CustId=c.IdQuestion 1: Will this work?
That would not work - it will complain about needing a GROUP BY clause. To get what you are looking for, you can do this:SELECT c.*, COUNT(a.Id) OVER(PARTITION BY c.ID) AS InvoiceCountFROM Customers c, INvoice aWHERE c.ID=@custId AND a.CustId=c.Id If you are limiting the query to one custId, you can remve the "PARTITION BY c.ID" and just have "OVER ()". For your more complex query, the approach would be exactly the same. |
 |
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2012-06-15 : 11:19:26
|
Using an aggregate function with an OVER clause works great. However, sometimes, it's harder for people to wrap their mind around the concept. Here is another way using a derived (or inline) table:SELECT c.*, a.InvoiceCountFROM Customers AS c INNER JOIN ( SELECT CustID, COUNT(*) AS InvoiceCount FROM Invoice WHERE CustID = @custId GROUP BY CustID ) AS a ON c.Id = a.CustId |
 |
|
kpgraci
Yak Posting Veteran
68 Posts |
Posted - 2012-06-15 : 11:37:17
|
Brilliant. Thanks both! I like the OVER clause becauce it is short and sweet, but true, I don't understand what it's doing at this point time, I'll look it up.Both were very helpful, thanks.kpg |
 |
|
|
|
|
|
|