【问题标题】:Dynamically creating date periods using MySQL使用 MySQL 动态创建日期期间
【发布时间】:2012-03-04 05:10:42
【问题描述】:

我试图获取 3 月 1 日至 3 日日期的葡萄数量。

您会注意到在 3 月 2 日 - 没有插入葡萄..

我无法显示日期为 3 月 1 日、2 日和 3 日的查询,但显示 3 月 2 日的计数为 0

在上图中只显示了有葡萄的日期..

这是 mySQL 查询

SELECT  `fruitDate` ,  `fruitName` , COUNT( * ) 
FROM  `tbl_fruits` 
WHERE  `fruitName` =  "Grapes"
GROUP BY  `fruitDate

更新 2:

使用这个查询:

SELECT f.fruitDate, f.fruitName, f1.count FROM tbl_fruits f
    LEFT JOIN (SELECT fruitDate, COUNT(*) as count from tbl_fruits d WHERE d.fruitName='Grapes' GROUP BY d.fruitDate) as f1 ON (f.fruitDate = f1.fruitDate) 
    GROUP BY f.fruitDate

我得到了这个结果..但是它显示不同的水果..我的查询有问题吗?

【问题讨论】:

标签: php mysql database


【解决方案1】:

3 月 2 日是您的表中不存在的数据,它会从什么中选择?也就是说,由于count() 正在统计每个日期 exist 为 "Grapes" 的行数,而 3 月 2 日的 "Grapes" 没有行数,count() 没有数据计数,根本没有告诉数据库插入丢失的日期。

为了解决这个问题,我过去所做的是创建一个单独的表,日历,其中包含给定范围内每个日期的一行。然后,您可以JOIN 到此表,以确保您为每个日期选择一行。它可能看起来像这样:

SELECT cal.`Date`, 'Grapes' as `fruitName`, COUNT(f.`fruitName`)
FROM `tbl_Calendar` cal 
LEFT JOIN `tbl_fruits` f ON cal.`Date` = f.`fruitDate`  
WHERE `fruitName` = "Grapes"
 AND '2012-03-01' <= cal.`Date` AND cal.`Date` <= '2012-03-03' 
GROUP BY cal.`Date`

请注意,count(*) 永远不会返回 0,因为每个日期都会返回一行。要获得 0,请在找到 0 行时计算一个为 NULL 的字段,在这种情况下,我计算 fruitName

日历表可以很简单

CREATE TABLE tbl_Calendar (
  `Date` date NOT NULL PRIMARY KEY
)

您将使用一个从选定开始日期到结束日期的简单 PHP 循环来填充它。您可能会发现添加其他列来缓存诸如星期几或假期之类的内容会有好处,但这不是此任务所必需的。

编辑

在您的编辑中,您似乎试图重新加入您的水果表以获取日期,但您的查询中有一些错误,请尝试用类似的子查询代替我的日历表:

SELECT cal.`Date`, 'Grapes' as `fruitName`, COUNT(f.`fruitName`)
FROM (SELECT `fruitDate` as `Date` FROM `tbl_fruits` GROUP BY `fruitDate`) cal 
LEFT JOIN `tbl_fruits` f ON cal.`Date` = f.`fruitDate`  
WHERE `fruitName` = "Grapes"
GROUP BY cal.`Date`

但是请注意,虽然这将填补葡萄缺失的日期,而某些其他水果没有缺失,但它不会填补所有水果缺失的日期。

【讨论】:

  • 你能告诉我你在这个例子中创建的表名和字段吗?我想复制它以使用此代码..
  • 我不确定你的意思,也许琐碎的 CREATE 会有所帮助?
  • 谢谢你的帮助伞……我对你所说的“3 月 2 日是你的表中不存在的数据”有点困惑,我的 tbl_fruits 表在我的第一张截图上问题。我的查询结果是仅显示 3 月 1 日和 3 日的第二张屏幕截图。我的查询是第三张截图..:)
  • 我想这归结为意见,但我认为在保持架构清洁方面将缺失的日期插入应用程序代码而不是数据层会是一个更好的解决方案。
  • 感谢您的帮助。我试过这个查询: SELECT f.fruitDate, f.fruitName, f1.count FROM tbl_fruits f LEFT JOIN (SELECT fruitDate, COUNT(*) as count from tbl_fruits d WHERE d.fruitName='Grapes' GROUP BY d.fruitDate) as f1 ON (f.fruitDate = f1.fruitDate) GROUP BY f.fruitDate..但是我得到了一个不同的水果名称..我的查询有什么问题吗?查看更新的屏幕截图
【解决方案2】:

请记住,有一个动态(而且有点难看)的解决方案来创建不需要创建表格的日期范围:

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

根据日期范围的长度,您可以通过删除表(d、c、b 和 a)并将它们从上式。设置 @minDate@maxDate 变量将允许您指定过滤结果之间的日期。

编辑:

我看到您仍在寻找解决方案。试试这个:

select c.date, f.fruitName, count(f.fruitName = 'Grapes')
from tbl_calendar c
left join tbl_fruits f
on c.date = f.fruitDate and f.fruitName = 'Grapes'
group by c.date, f.fruitName

如果您还想从创建的表中过滤掉多余的日期,请使用以下查询:

select c.date, f.fruitName, count(f.fruitName = 'Grapes')
from tbl_calendar c
left join tbl_fruits f
on c.date = f.fruitDate and f.fruitName = 'Grapes'
group by c.date, f.fruitName
having c.date between
  (select min(fruitDate) from tbl_fruits) and
  (select max(fruitDate) from tbl_fruits)

【讨论】:

  • uh..这让我的眼睛酸痛..lol..我知道这个但我认为这是太多的代码..LOL..无论如何还是谢谢/.我将来也可能会使用它..
  • 我喜欢你的第一个代码。但是如果查询中没有葡萄,它会返回一个空值。我们可以显示葡萄而不是空吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多