Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL query involving group by and joins

I couldn't be more specific in the title part but I want to do something a little bit complex for me. I thought I did it but it turned out that it is buggy.

I have three tables as following:

ProjectTable

  • idProject
  • title
  • idOwner

OfferTable

  • idOffer
  • idProject
  • idAccount

AccountTable

  • idAccount
  • Username

Now in one query I aim to list all the projects with most offers made, and in the query I also want to get details like the username of the owner, username of the offerer* etc. So I don't have to query again for each project.

Here is my broken query, it's my first experiment with GROUP BY and I probably didn't quite get it.

SELECT Project.addDate,Project.idOwner ,Account.Username,Project.idProject,
    Project.Price,COUNT(Project.idProject) as offercount 
FROM Project 
INNER JOIN Offer 
    ON Project.idProject= Offer.idProject 
INNER JOIN Account 
ON Account.idAccount = Project.idOwner  
GROUP BY Project.addDate,Project.idOwner,
    Account.Username,Project.idProject,Project.Price 
ORDER BY addDate DESC

*:I wrote that without thinking I was just trying to come up with example extra information, that is meaningless thanks to Hosam Aly.

like image 988
EralpB Avatar asked Jan 15 '23 13:01

EralpB


2 Answers

Try this (modified for projects with no offers):

SELECT
  Project.addDate,
  Project.idOwner,
  Account.Username,
  Project.idProject,
  Project.Price,
  ISNULL(q.offercount, 0) AS offercount
FROM
  (
    SELECT
      o.idProject,
      COUNT(o.idProject) as offercount
    FROM Offer o
    GROUP BY o.idProject
  ) AS q
  RIGHT JOIN Project ON Project.idProject = q.idProject
  INNER JOIN Account ON Account.idAccount = Project.idOwner
ORDER BY addDate DESC
like image 164
Mike Perrenoud Avatar answered Jan 22 '23 04:01

Mike Perrenoud


I might switch the query slightly to this:

select p.addDate,
  p.idOwner,
  a.Username,
  p.idProject,
  p.price,
  o.OfferCount
from project p
left join
(
  select count(*) OfferCount, idproject
  from offer
  group by idproject
) o
  on p.idproject = o.idproject
left join account a
  on p.idowner = a.idaccount

This way, you are getting the count by the projectid and not based on all of the other fields you are grouping by. I am also using a LEFT JOIN in the event the projectid or other id doesn't exist in the other tables, you will still return data.

like image 28
Taryn Avatar answered Jan 22 '23 04:01

Taryn