我的数据跨越了多个月,我希望能够获得每天的平均值并将其分成适当的月份。例如,假设一个数据点是2/9/2010 - 3/8/2010,金额为1500.那么,查询应返回2010年2月的1071.4和3月的428.6。我希望有一个MySQL语句能够进行计算而不是我的PHP逻辑。感谢。
编辑(添加表定义): start(datetime),end(datetime),use
编辑2:这是一些虚拟数据
DROP TABLE IF EXISTS `dummy_data`;
CREATE TABLE `dummy_data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start_date` date NOT NULL,
`end_date` date NOT NULL,
`data` double(15,4) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of `dummy_data`
-- ----------------------------
BEGIN;
INSERT INTO `dummy_data` VALUES ('1', '2010-01-01', '2010-02-02', '200.0000'), ('2', '2010-02-03', '2010-02-25', '250.0000'), ('3', '2010-02-26', '2010-03-08', '300.0000'), ('4', '2010-03-09', '2010-04-12', '210.0000'), ('5', '2010-04-13', '2010-05-10', '260.0000'), ('6', '2010-05-11', '2010-06-15', '310.0000'), ('7', '2010-06-16', '2010-07-20', '320.0000');
COMMIT;
答案 0 :(得分:1)
您应该按MONTH(日期)功能选择SUM和分组,如下所示:
SELECT SUM(value), MONTH(date)
FROM TABLE
GROUP BY MONTH(date)
编辑:哎呀,我误解了这个问题,现在修改我的答案!
您需要使用一些更复杂的TSQL来获取月中的天数,找到平均值并设置到每个字段然后以月度格式显示
<强>更新强> 创建一个函数,为您提供范围内的日期,例如我从Michael Baria创建的函数修改过的日期
CREATE FUNCTION [dbo].[GetDays](@StartDate DATETIME, @EndDate DATETIME)
RETURNS @MonthList TABLE(DayValue tinyint NOT NULL, MonthValue tinyint NOT NULL, YearValue int NOT NULL)
AS
BEGIN
--Variable used to hold each new date value
DECLARE @DateValue DATETIME
--Start with the starting date in the range
SET @DateValue=@StartDate
--Load output table with the month part of each new date
WHILE @DateValue <= @EndDate
BEGIN
INSERT INTO @MonthList(DayValue, MonthValue,YearValue)
SELECT DAY(@DateValue), MONTH(@DateValue), YEAR(@DateValue)
--Move to the next day
SET @DateValue=DATEADD(dd,1,@DateValue)
END
--Return results
RETURN
END
GO
将您的桌子加入此功能,然后根据天数加总
SELECT SUM(data/DATEDIFF(dd,startDate,endDate)), M.MonthValue
FROM TABLE
JOIN (SELECT * FROM [dbo].[GetDays] (startDate,endDate)) M
GROUP BY M.MonthValue
如果我得到一些样本数据,我可以稍微清理一下
答案 1 :(得分:1)
此解决方案处理的[start_date, end_date]
跨度只有一(1)天,最长可达十二(12)个月,但在十三(13)个月或更长时间内不正确:
CREATE TABLE integers (i INT NOT NULL);
INSERT INTO integers VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
CREATE VIEW hundreds AS
SELECT iii.i * 100 + ii.i * 10 + i AS i
FROM integers i JOIN integers ii JOIN integers iii;
-- We do not have CTEs, so we create a view
CREATE VIEW spans AS
SELECT id, start_date, DATEDIFF(end_date, start_date) + 1 AS ndays, data
FROM dummy_data;
SELECT spans.id,
month_name,
spans.data * COUNT(month_name)/spans.ndays AS month_amount
FROM spans
LEFT JOIN (SELECT id,
MONTH(start_date + INTERVAL i DAY) AS month_num,
MONTHNAME(start_date + INTERVAL i DAY) AS month_name
FROM spans
JOIN hundreds WHERE i < ndays) daybyday
ON spans.id = daybyday.id
GROUP BY id, month_name
ORDER BY id, month_num;
输出如下:
+----+------------+---------------+
| id | month_name | month_amount |
+----+------------+---------------+
| 1 | January | 187.87878788 |
| 1 | February | 12.12121212 |
| 2 | February | 250.00000000 |
| 3 | February | 81.81818182 |
...
我们使用DATEDIFF
来确定源记录所代表的天数。然后,建立一个integers table,我们可以枚举特定范围内每一天的月份。从那里开始记录id
和month_name
的SQL聚合问题。
答案 2 :(得分:0)
这确实将金额分开:
declare @start datetime set @start = '20100209'
declare @end datetime set @end = '20100308'
declare @avg float set @avg = 1500
select
datediff(day, @start, dateadd(day, 1-day(@end), @end)) * @avg / (datediff(day, @start, @end) + 1),
datediff(day, dateadd(day, -day(@end), @end), @end) * @avg / (datediff(day, @start, @end) + 1)
结果:
1071,42857142857 428,571428571429
虽然它变得有点复杂,因为你首先要检查日期是否实际上在不同月份,如果日期超过两个月你需要采用不同的方法。