Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.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 - Fatal编程技术网

如何在MySQL中生成数据?

如何在MySQL中生成数据?,mysql,sql,Mysql,Sql,以下是我的SQL: SELECT COUNT(id), CONCAT(YEAR(created_at), '-', MONTH(created_at), '-', DAY(created_at)) FROM my_table GROUP BY YEAR(created_at), MONTH(created_at), DAY(created_at) 我希望即使在没有创建ID的日子里也能显示一行。现在我错过了很多没有活动的日子 关于如何更改此查询以实现此目的,您有什么想法吗?众所周知,S

以下是我的SQL:

SELECT 
  COUNT(id),
  CONCAT(YEAR(created_at), '-', MONTH(created_at), '-', DAY(created_at))
FROM my_table
GROUP BY YEAR(created_at), MONTH(created_at), DAY(created_at)
我希望即使在没有创建ID的日子里也能显示一行。现在我错过了很多没有活动的日子


关于如何更改此查询以实现此目的,您有什么想法吗?

众所周知,SQL不善于返回数据库中没有的数据。您可以找到日期间隔的起始值和结束值,但获取所有日期很困难

解决方案是创建一个日历表,每个日期有一条记录,并将其连接到查询中

下面是一个假设在类型日期创建的_的示例:

SELECT calendar_date, COUNT(`id`)
FROM calendar LEFT OUTER JOIN my_table ON calendar.calendar_date = my_table.created_at
GROUP BY calendar_date

(我猜创建的时间实际上是DATETIME,所以你必须做更多的体操才能加入到表格中)。

总体思路

MySQL中有两种主要的数据生成方法。一种是在运行查询时动态生成数据,另一种是将数据保存在数据库中,并在必要时使用它。当然,如果要经常运行查询,第二个将比第一个更快。但是,第二种方法需要数据库中的一个表,该表的唯一目的是生成缺少的数据。它还要求您具有足够的权限来创建该表

动态数据生成

这种方法涉及到创建
联合
s以生成一个伪表,该表可用于将实际表与。可怕且重复的查询是:

select aDate from (
  select @maxDate - interval (a.a+(10*b.a)+(100*c.a)+(1000*d.a)) day aDate from
  (select 0 as a union all select 1 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) a, /*10 day range*/
  (select 0 as a union all select 1 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) b, /*100 day range*/
  (select 0 as a union all select 1 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) c, /*1000 day range*/
  (select 0 as a union all select 1 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) d, /*10000 day range*/
  (select @minDate := '2001-01-01', @maxDate := '2002-02-02') e
) f
where aDate between @minDate and @maxDate
无论如何,这比看起来要简单。它使用
10
数值生成派生表的笛卡尔积,因此结果将有
10^X
行,其中
X
是查询中派生表的数量。在本例中,有
10000
天范围,因此您可以表示超过
27
年的周期。如果需要更多,请向查询中添加另一个
UNION
并更新间隔,如果不需要那么多,可以从派生表中删除
UNION
或单个值。为了澄清这一点,您可以通过对
@minDate
@maxDate
变量应用带有
WHERE
子句的筛选器来微调日期周期(但不要使用比您使用笛卡尔积创建的周期更长的周期)

静态数据生成

此解决方案将要求您在数据库中生成一个表。该方法与前一种方法类似。您必须首先将数据插入该表:从
1
X
的整数范围,其中
X
是所需的最大范围。同样,如果您不确定,只需插入
100000
值,就可以创建超过
273
年的日范围。因此,一旦获得整数序列,就可以将其转换为如下所示的日期范围:

select '2012-01-01' + interval value - 1 day aDay from seq
having aDay <= '2012-01-05'
select (select min(aDate) from domainTable) + interval value - 1 day aDay
from seq
having aDay <= (select max(aDate) from domainTable)
这将生成一个包含所有所需天数的派生表(注意,我使用的是静态数据生成),并对我们的域表执行
左联接
,因此所有天数都将显示,无论它们在我们的域表中是否有匹配的值。另请注意,
count
应在具有
null
值的字段上执行,因为这些值未被计数

需要考虑的注释

1) 这些查询可用于查询对代码执行微小更改的其他时间间隔(月、年)

2) 不必硬编码日期,您可以从域表中查询
min
max
值,如下所示:

select '2012-01-01' + interval value - 1 day aDay from seq
having aDay <= '2012-01-05'
select (select min(aDate) from domainTable) + interval value - 1 day aDay
from seq
having aDay <= (select max(aDate) from domainTable)
如您所见,查询的框架与前一个相同。唯一改变的是如何生成派生表
allDays
。现在,派生表的生成方式也与我之前添加的略有不同。这是因为在示例filddle中,我只需要
10
-天的范围。如您所见,它比添加
1000
日范围更具可读性。下面是动态解决方案的示例,以便您也可以使用它

希望这有帮助

试验台:

create table testbed(id integer,在日期创建);
插入到测试床值中
(1, '2012-04-01'),
(1, '2012-04-30'),
(2, '2012-04-02'),
(3, '2012-04-03'),
(3, '2012-04-04'),
(4, '2012-04-04');
我还使用了
任意_表
,这是我人工创建的,如下所示:

select '2012-01-01' + interval value - 1 day aDay from seq
having aDay <= '2012-01-05'
select (select min(aDate) from domainTable) + interval value - 1 day aDay
from seq
having aDay <= (select max(aDate) from domainTable)
创建表任意_表(id整数);
在任何_表中插入值(1)、(2)、(3)、(4)、(5)、(6)、(7)、(8)、(9)、(10);
插入到任意_表中,从任意_表中选择*重复此插入7-8次
您可以使用数据库中任何一个表,该表的行数超过
max(created_dt)-min(created_dt)
范围,至少365行,覆盖一年

查询:

选择concat(年(博士日期),'-',月(博士日期),'-',日(博士日期)),
--或者,代替concat(),只需:dr.(u date)
计数(id)
从(
选择日期\u添加(r.mindt,dist day的间隔)\u日期,
@距离:=@dist+1天
从任何表t
加入(选择min(创建时)mindt,
最大值(在最大值处创建),
@距离:=0
从试验台)r

WHERE date_add(r.mindt,INTERVAL@dist day)在一个查询中执行此操作的方法:

选择COUNT(my_table.id)作为总计,
CONCAT(年(dates.ddate),“-”,月(dates.ddate),“-”,日(dates.ddate))
从(
--从2000-01-01(179年)开始创建“动态”65536天
选择日期添加(“2000-01-01”,时间间隔(b1.b+b2.b+b3.b+b4.b+b5.b+b6.b+b7.b+b8.b+b9.b+b10.b+b11.b+b12.b+b13.b+b14.b+b15.b+b16.b)天)作为起始日期
(选择0作为b联合选择1)b1,
(选择0作为b联合选择2)b2,
(选择0作为b联合选择4)b3,
(选择0作为b联合选择8)b4,
(选择0作为b联合选择16)b5,
(选择0作为b联合选择32)b6,
(选择