I have 1 table with similar data:
CustomerID | ProjectID | DateListed | DateCompleted
123456 | 045 | 07-29-2010 | 04-03-2011
123456 | 123 | 10-12-2011 | 11-30-2011
123456 | 157 | 12-12-2011 | 02-10-2012
123456 | 258 | 06-07-2011 | NULL
Basically, a customer contacts us, we get a project on our list, and we mark it completed when we’re done with it.
What I’m after is a simple (you’d think, at least) count of all projects, with expected output like below:
YEAR | TotalListed | TotalCompleted
2010 | 1 | 0
2011 | 3 | 2
2012 | 0 | 1
However, my query below – because of the join – isn’t showing 2012’s count, because there’s been no listed project for 2012. However, I can’t really reverse the query, as then 2010’s count wouldn’t show up (since nothing was completed in 2010).
I’m open to any suggestions, or tips like how to do this. I’ve pondered a temp table, is that the best way to go? I’m open to anything that gets me what I need!
(If the code looks familiar, ya’ll helped me get the subquery made! MySQL Subquery with main query data variable)
SELECT YEAR(p1.DateListed) AS YearListed, COUNT(p1.ProjectID) As Listed, PreQuery.Completed
FROM(
SELECT YEAR(DateCompleted) AS YearCompleted, COUNT(ProjectID) AS Completed
FROM projects
WHERE CustomerID = 123456 AND DateListed >= DATE_SUB(Now(), INTERVAL 5 YEAR)
GROUP BY YEAR(DateCompleted)
) PreQuery
RIGHT OUTER JOIN projects p1 ON PreQuery.YearCompleted = YEAR(p1.DateListed)
WHERE CustomerID = 123456 AND DateListed >= DATE_SUB(Now(), INTERVAL 5 YEAR)
GROUP BY YearListed
ORDER BY p1.DateListed
After reviewing your table, query, and expected results – I believe I have found a more-revised query to suit your needs. It is a fairly-full rewrite of your existing query though, but I’ve tested it with your given data and received the same results you want/expect:
To explain, we should start with the inner query (aliased as
year_inner). It selects a full list of years in theDateListedandDateCompletedcolumns and then selects aDISTINCTlist of those to create theyearsalias sub-query. This sub-query is used to get a full list of “years” that we want data for. Doing it this way, opposed to a sub-query with counts and groupings will allow you to only have to define theWHEREclause on the outermost query (though, if efficiency becomes an issue with thousands and thousands of records, you could always add aWHEREclause to the inner query too; or an index to the date columns).After we’ve built our inner queries, we join the
projectstable on the results with aLEFT JOINfor theDateListedorDateCompleted‘sYEAR()value – which will allow us to bring backnullcolumns too!For the field selections, we use the
yearcolumn from our inner query to assure that we get a full list of years to display. Then, we compare the current row’s DateListed & DateCompletedYEAR()value to the current year; if they’re equal, add 1 – else add 0. When weGROUP BY year, ourSUM()will count all of the 1’s for that year for each column and give you the output you want (hopefully, of course =P).