MySQL - 当某些年份为空时计算年度总计

时间:2012-10-05 23:49:09

标签: mysql subquery

我有一张包含类似数据的表:

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

1 个答案:

答案 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)。它会在DateListedDateCompleted列中选择完整的年份列表,然后会选择DISTINCT列表来创建years别名子列表-query。此子查询用于获取我们想要数据的“年”的完整列表。这样做,与具有计数和分组的子查询相反,将允许您只需要在最外层查询上定义WHERE子句(但是,如果效率成为成千上万条记录的问题,那么你总是可以在内部查询中添加WHERE子句;或者在日期列中添加索引。

在我们构建了内部查询之后,我们将projects表添加到LEFT JOIN {{1} DateListed的结果中} DateCompleted值 - 这样我们也可以带回YEAR()列!

对于字段选择,我们使用内部查询中的null列来确保我们获得要显示的完整年份列表。然后,我们比较当前行的DateListed& DateCompleted year到当前年份的值;如果它们相等,则添加1 - 否则添加0.当我们YEAR()时,我们的GROUP BY year将计算每一列中每一列的所有1,并为您提供所需的输出(希望,当然= P)。