2

我有 1 个包含类似数据的表:

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 子查询

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
4

1 回答 1

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别名子查询。此子查询用于获取我们想要数据的“年”的完整列表。这样做,与具有计数和分组的子查询相反,您只需WHERE在最外层查询上定义子句(但是,如果效率成为成千上万条记录的问题,您总是可以添加一个WHERE子句到内部查询;或日期列的索引)。

在我们构建了我们的内部查询之后,我们projects用一个LEFT JOINfor DateListed or DateCompletedYEAR()值将结果表连接起来——这也将允许我们带回null列!

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

于 2012-10-06T01:28:14.713 回答