我有一张包含类似数据的表:
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
基本上,客户与我们联系,我们会在列表中找到一个项目,并在完成后将其标记为已完成。
我所追求的是一个简单的(你至少想到)所有项目的数量,预期输出如下:
YEAR | TotalListed | TotalCompleted
2010 | 1 | 0
2011 | 3 | 2
2012 | 0 | 1
但是,我的查询 - 由于加入 - 未显示2012年的计数,因为2012年没有列出的项目。但是,我无法真正反转查询,因为2010年的计数不会显示(因为2010年没有完成任何事情)。
我愿意接受任何建议,或提示如何做到这一点。我考虑过临时表,这是最好的方法吗?我愿意接受任何让我得到我需要的东西!
(如果代码看起来很熟悉,你会帮助我得到子查询!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
答案 0 :(得分:1)
在审核了您的表格,查询和预期结果后 - 我相信我找到了一个更符合您需求的更新修改查询。虽然这是对现有查询的完全重写,但我已经使用您的给定数据对其进行了测试,并获得了您想要/期望的相同结果:
SELECT
years.`year`,
SUM(IF(YEAR(DateListed) = years.`year`, 1, 0)) AS TotalListed,
SUM(IF(YEAR(DateCompleted) = years.`year`, 1, 0)) AS TotalCompleted
FROM
projects
LEFT JOIN (
SELECT DISTINCT `year` FROM (
SELECT YEAR(DateListed) AS `year` FROM projects
UNION SELECT YEAR(DateCompleted) AS `year` FROM projects WHERE DateCompleted IS NOT NULL
) as year_inner
) AS years
ON YEAR(DateListed) = `year`
OR YEAR(DateCompleted) = `year`
WHERE
CustomerID = 123456 AND DateListed >= DATE_SUB(Now(), INTERVAL 5 YEAR)
GROUP BY
years.`year`
ORDER BY
years.`year`
为了解释,我们应该从内部查询开始(别名为year_inner
)。它会在DateListed
和DateCompleted
列中选择完整的年份列表,然后会选择DISTINCT
列表来创建years
别名子列表-query。此子查询用于获取我们想要数据的“年”的完整列表。这样做,与具有计数和分组的子查询相反,将允许您只需要在最外层查询上定义WHERE
子句(但是,如果效率成为成千上万条记录的问题,那么你总是可以在内部查询中添加WHERE
子句;或者在日期列中添加索引。
在我们构建了内部查询之后,我们将projects
表添加到LEFT JOIN
或 {{1} DateListed
的结果中} DateCompleted
值 - 这样我们也可以带回YEAR()
列!
对于字段选择,我们使用内部查询中的null
列来确保我们获得要显示的完整年份列表。然后,我们比较当前行的DateListed& DateCompleted year
到当前年份的值;如果它们相等,则添加1 - 否则添加0.当我们YEAR()
时,我们的GROUP BY year
将计算每一列中每一列的所有1,并为您提供所需的输出(希望,当然= P)。