Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 为日期范围生成数据,包括数据中不存在的日期_Mysql_Sql_Datetime_Date Range - Fatal编程技术网

Mysql 为日期范围生成数据,包括数据中不存在的日期

Mysql 为日期范围生成数据,包括数据中不存在的日期,mysql,sql,datetime,date-range,Mysql,Sql,Datetime,Date Range,以下是我的表格结构和数据: CREATE TABLE event ( EventID INT(11) NOT NULL AUTO_INCREMENT, EventDate DATETIME DEFAULT NULL, Description VARCHAR(50) DEFAULT NULL, PRIMARY KEY (EventID) ); INSERT INTO event (EventID, EventDate, Description) VALUES

以下是我的表格结构和数据:

CREATE TABLE event (
    EventID INT(11) NOT NULL AUTO_INCREMENT,
    EventDate DATETIME DEFAULT NULL,
    Description VARCHAR(50) DEFAULT NULL,
    PRIMARY KEY (EventID)
);

INSERT INTO event (EventID, EventDate, Description) VALUES
    (1, '2011-01-01 00:00:00', 'Event 1'),
    (2, '2011-03-01 00:00:00', 'Event 2'),
    (3, '2011-06-01 00:00:00', 'Event 3'),
    (4, '2011-09-01 00:00:00', 'Event 4');
此查询和输出:

SELECT *
FROM EVENT
WHERE EventDate BETWEEN '2011-02-01' AND '2011-03-31'
+---------+---------------------+-------------+
|事件ID |事件日期|描述|
+---------+---------------------+-------------+
|2 | 2011-03-01 00:00:00 |事件2|
+---------+---------------------+-------------+
一行一组(0.00秒)
我希望在结果中插入空日期,如下所示:

+---------+---------------------+-------------+
|事件ID |事件日期|描述|
+---------+---------------------+-------------+
|空| 2011-02-01 00:00:00 |空|
|空| 2011-02-02 00:00:00 |空|
|空| 2011-02-03 00:00:00 |空|
∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨
∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧
|空| 2011-02-28 00:00:00 |空|
|2 | 2011-03-01 00:00:00 |事件2|
|空| 2011-03-02 00:00:00 |空|
∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨
∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧
|空| 2011-03-31 00:00:00 |空|
+---------+---------------------+-------------+
输出应该包含59行:2月28行,3月31行


我希望避免任何硬编码;相反,我需要一个非常灵活的解决方案来适应指定的日期。

我确信这在纯SQL中是不可能的,因此您可以选择:

  • 使用存储过程/函数
  • 在应用程序代码中这样做,这看起来很简单

一个辅助日历表可以很好地工作。最简单的日历表是一列日期

create table calendar (
    cal_date date primary key
);
您可以使用电子表格或SQL来填充它。它的外部联接将引入数据中不存在的日期。使用GRANT和REVOKE限制权限,并使用任何必要的方法来确保您希望在其中的日期确实在那里。我在服务器上运行每日报告,确保有“n”行,并验证最早和最新日期


在某些平台上,您可以动态生成一系列日期,并直接使用或在CTE中使用。PostgreSQL有相应的函数;我不知道MySQL是否有。不过,如果你想自己写,它们并不难写。

也许你需要一个数据透视表,看看吧

数据透视表模式

名称:pivot 列:{i:datatype int}

填充

创建foo表

模式foo

姓名:富 列:值数据类型varchar

insert into foo
values('0'),
values('1'),
values('2'),
values('3'),
values('4'),
values('5'),
values('6'),
values('7'),
values('8'),
values('9');

- insert 100 values
insert into pivot
select concat(a.value, a.value)
from foo a, foo b

- insert 1000 values
insert into pivot
select concat(a.value, b.value, c.value)
from foo a, foo b, foo c
你的问题

SELECT 
 Event.EventId,
 case when EventDate is null then DATE_ADD(periods.periodstart, INTERVAL auxtable.i DAY)
 else EventDate  end,
 Description

FROM
(
  select id, min(EventDate ) periodstart, max(EventDate) periodend,

  DATEDIFF(max(EventDate),min(EventDate )) as days
  FROM EVEN
  WHERE EventDate BETWEEN '2011-02-01' AND '2011-03-31'
) periods

inner join     

(
  select *
  from pivot
  where i >= 0 and i < 31 //max one month change with your needs
)auxtable
on auxtable.i < periods.days

left join Event
on Event.EventDate = DATE_ADD(periods.periodstart, INTERVAL auxtable.i DAY)
选择
Event.EventId,
如果EventDate为空,则为DATE_ADD(periods.periodstart,INTERVAL auxtable.i DAY)
否则事件日期结束,
描述
从…起
(
选择id、最小(事件日期)周期开始、最大(事件日期)周期结束,
DATEDIFF(最大(事件日期),最小(事件日期))作为天数
平分
其中,事件日期介于“2011-02-01”和“2011-03-31”之间
)时期
内连接
(
挑选*
从枢轴
其中i>=0且i<31//根据您的需要最多可更改一个月
)可折叠
在auxtable.i
+1:与预先创建的表进行比较要比编写代码来计算单个缺失的日期快得多。@Dems:这也不灵活。它确实取决于日期范围的变化。@pablochan:我不会说它是不灵活的。100年的日历所占空间约为16KB;如果需要的话,动态创建它的时间是微不足道的;它可以定制为具有诸如DayOfWeek、BankHoliday、开放时间等字段;它可以是由天、小时、周、月等组成的日历;你几乎可以用它做任何你喜欢的事情。几乎在所有情况下,这都是一个巨大的性能提升。无论代价有多大,灵活性都不是其中之一。您可能希望避免“硬编码”,但高效地创建日期列表、比较、插入(甚至删除列表)将比尝试计算单个日期快得多。@Dems:您可能是对的,我没想到它会起作用,但太复杂了。此外,它还需要我填充序列号表。这是一种来自更纯sql的神秘技术。sql server采用了“pivot”指令,我从来不需要阅读它,但毫无疑问,它更简单,但我更喜欢便携式sql,不过我会密切关注