即使缺少月份,也会按月计算总计

Posted

技术标签:

【中文标题】即使缺少月份,也会按月计算总计【英文标题】:totals by month even for if there is a missing month 【发布时间】:2015-01-27 23:46:46 【问题描述】:

只是一个快速的,希望....

我只从一个表中按月获取了一些总计(销售价值)。

我遇到的问题是: 如果一个月没有销售,则结果中当然不会返回该月份。有没有办法我可以在一个查询中做到这一点,所以如果没有销售,即“2015 年 1 月”,结果将返回“0.00 - 2015 年 1 月”

我目前拥有的基本SQL是:

SELECT SUM(p.PaymentAmount) AS Total, MONTHNAME(p.PaymentDate) AS Month, YEAR(p.PaymentDate) AS Year
FROM tPayment p
WHERE p.PaymentType = 2
GROUP BY YEAR(p.PaymentDate), MONTH(p.PaymentDate)

如果不选择 php 中的日期范围然后查询每个月和年,我想不出该怎么做...这看起来很乱...所以我想知道我是否可以在单个查询中执行此操作.

非常感谢任何帮助!

【问题讨论】:

您可以在销售字段中为 1 月添加一行 0。 PHP端填空会不会有问题? 考虑nested queries。 也许一个月表与left join 到支付表? 这看起来是你正在做的,但不是一个简单的查询***.com/questions/27600863/… 【参考方案1】:

您应该为自己创建一个单独的表格,其中包含日期,例如

CREATE TABLE `dates` (
    `uid` INT NOT NULL AUTO_INCREMENT,
    `datestamp` DATE NOT NULL,
PRIMARY KEY (`uid`))
ENGINE = InnoDB;

然后填写

INSERT INTO dates (datestamp)
SELECT ADDDATE('2015-01-01', INTERVAL SomeNumber DAY)#set start date
FROM (SELECT a.i+b.i*10+c.i*100+d.i*1000 AS SomeNumber 
    FROM integers a,  integers b, integers c, integers d) Sub1
WHERE SomeNumber BETWEEN 0 AND (365 * 3)#3 years

那么你可以加入反对它

SELECT SUM(p.PaymentAmount) AS Total, MONTHNAME(p.PaymentDate) AS Month, YEAR(p.PaymentDate) AS Year
FROM tPayment p
LEFT OUTER JOIN dates d
    ON d.datestamp = CAST(p.PaymentDate AS DATE)
WHERE p.PaymentType = 2
GROUP BY YEAR(p.PaymentDate), MONTH(p.PaymentDate)
ORDER BY d.datestamp DESC;

不管我是否在这里粗略地提出了查询,这个概念应该适合你

【讨论】:

【参考方案2】:

这不是我完成此任务的首选方法,但为了提供多种替代方法,如果您尝试将其全部保存在 mysql 中并避免创建额外的表,我会提供此方法。

SELECT 
    SUM(p.PaymentAmount) AS Total, 
    MONTHNAME(p.PaymentDate) AS Month, 
    YEAR(p.PaymentDate) AS Year
FROM ( SELECT 1 AS m UNION ALL 
    SELECT 2 UNION ALL 
    SELECT 3 UNION ALL 
    SELECT 4 UNION ALL 
    SELECT 5 UNION ALL 
    SELECT 6 UNION ALL 
    SELECT 7 UNION ALL 
    SELECT 8 UNION ALL 
    SELECT 9 UNION ALL 
    SELECT 10 UNION ALL 
    SELECT 11 UNION ALL 
    SELECT 12
) AS months
OUTER JOIN tPayment p
    ON MONTH(p.PaymentDate) = months.m
WHERE p.PaymentType = 2
GROUP BY YEAR(p.PaymentDate), MONTH(p.PaymentDate)

我认为在运行查询后在一些快速的 PHP 代码中检查它会更容易。

正如Jon B 所建议的那样,创建一个 months 表并加入该表将大大缩短和清理查询。如果你想把它全部保留在你的 MySQL 查询中,我个人会选择他的方法。

【讨论】:

【参考方案3】:

如果您的表中有所有月份的数据——但where 子句过滤掉了一个或多个月份的所有行——你可以尝试条件聚合:

SELECT SUM(CASE WHEN p.PaymentType = 2 THEN p.PaymentAmount ELSE 0 END) AS Total,
       MONTHNAME(p.PaymentDate) AS Month, YEAR(p.PaymentDate) AS Year
FROM tPayment p
GROUP BY YEAR(p.PaymentDate), MONTH(p.PaymentDate)

这不能保证有效(取决于数据)。但如果是这样,这是解决这个问题的最简单方法。

【讨论】:

这将适用于当前数据,但这只是因为至少存在一种 PaymentType 形式。但是,如果任何一个月都没有付款(尽管这永远不会发生),这对我来说是行不通的,所以我会依靠机会,这对我来说可能不是一个好习惯....(我不知道为什么否决票,对我来说似乎是一个合理的建议/选择......过去我的一些问题也发生过同样的事情......我们都必须在某个地方学习......) @福特。 . .答案中明确解释了这一点。这只是获得所需内容的一种更简单的方法,这可能取决于所使用的数据。

以上是关于即使缺少月份,也会按月计算总计的主要内容,如果未能解决你的问题,请参考以下文章

计算月份之间的总差

在报表生成器中从组总计中排除过滤的数据

按月列出分组数据,包括没有结果的月份

如何按月生成燃尽图

php mysql 数据按月统计 没有的月份怎样补0

按月份名称对 pandas 数据框系列进行排序