【问题标题】:Return how many records created, closed, and open for each day in a time period返回一个时间段内每天创建、关闭和打开的记录数
【发布时间】:2012-09-07 14:03:00
【问题描述】:

我有一个存储创建和关闭日期的表。我要做的是运行一个查询,在给定的时间段内为我提供每天创建的记录数、关闭的记录数以及打开的记录数。表结构:

+------------------------+
| Field      | Structure |
+------------+-----------+
| id         | int       |
| start_date | datetime  |
| close_date | datetime  |
+------------+-----------+

前两个查询不是问题 - 我现在正在处理的是:

SELECT COUNT(*), start_date FROM dates 
WHERE start_date BETWEEN 'start' AND 'end' 
GROUP BY start_date 
ORDER BY start_date ASC

SELECT COUNT(*), close_date FROM dates 
WHERE close_date BETWEEN 'start' AND 'end' 
GROUP BY close_date 
ORDER BY close_date ASC

第三个查询是一个问题 - 我可以让它告诉我在表中存在这一天的那一天打开了多少个,但我还没有弄清楚如何让它写出一行一年中的每一天,给我那天的计数。

这是第一个问题。

第二个是我想让它给我这样的结果,但我不知道该怎么做 - 在这里搜索给了我一些错误的开始,但没有任何可靠的结果。

+------------+--------+--------+--------+
|    Date    | Opened | Closed | Active |
+------------+--------+--------+--------+
| 2012-05-06 | 3      | 2      | 7      |
| 2012-05-07 | 2      | 0      | 9      |
| 2012-05-08 | 0      | 0      | 9      |
| 2012-05-09 | 0      | 3      | 6      |
+------------+--------+--------+--------+

如有必要,我完全愿意运行单独的查询,并在必要时用代码而不是 db 处理所有这些查询 - 我相当确定我可以将来自单个查询的所有查询数据写入单个数组并且只是循环通过它来构建报告,但我真的不喜欢。有什么建议吗?

【问题讨论】:

  • 您在哪里存储问题是否已关闭/处于活动状态?打开是我认为创建记录的时间。其他的呢? - 没关系,我刚刚注意到 close_date。

标签: php mysql


【解决方案1】:

此查询很棘手,因为您需要范围内每个日期的状态列表。

在此查询中,日期是在连接查询中生成的。 为此,我使用同一张表,假设它有

  • 记录数 >= 日期范围之间的日期数
  • id-s 必须是连续的,最多可达日期范围之间的日期数

您可以将其替换为您自己的日期列表生成子查询。

set @start :='2012-05-06';
set @end :='2012-05-09';

select cdate as Date
     , sum(start_date = cdate) Opened
     , sum(close_date = cdate or close_date is null) Closed
     , sum(start_date <= cdate and (close_date>cdate or close_date is null)) Active
from dates
join (select date(@start + interval id-1 day) cdate from dates where id <= to_days(@end)-to_days(@start)+1) d
  on start_date <= cdate and (close_date>=cdate or close_date is null)
where start_date <= @end 
  and (close_date >= @start or close_date is null)
group by cdate
order by cdate
;

【讨论】:

  • 不幸的是,这里没有第二个必要条件。这是一个固有的数据库,记录编号到处乱跳。我一直想对它们进行清理以解决这个问题,但它的优先级相对较低。话虽如此,该查询是一段非常好的代码,我可以将其用于我一直想做的其他一些事情。谢谢!
【解决方案2】:

仅使用 SQL 语句创建这样的聚合表确实很困难。您将需要使用子查询、UNION 语句和/或可能的存储过程来获取逻辑点,以便在您呈现表格时显示表格。

您已经拥有的两个查询比我上面提到的方法快得多。 PHP 数组肯定会帮助您获得所需的内容。

所以:

第 1 步

SELECT COUNT(*) AS active_before_start 
WHERE start_date < 'start'
AND close_date IS NULL

获取该号码并将其存储在 $active_before_start 中。

第 2 步

SELECT COUNT(*) AS total_opened, start_date FROM dates 
WHERE start_date BETWEEN 'start' AND 'end' 
GROUP BY start_date 
ORDER BY start_date ASC

将这些结果放在一个数组中

foreach ($results as $result)
{
    $key = $result->start_date;
    $final_table[$key]['date']   = $key;
    $final_table[$key]['opened'] = $result->total_opened;
}

第 3 步

SELECT COUNT(*) AS total_closed, close_date FROM dates 
WHERE close_date BETWEEN 'start' AND 'end' 
GROUP BY close_date 
ORDER BY close_date ASC

再次将它们存储在数组中

foreach ($results as $result)
{
    $key = $result->close_date;
    $final_table[$key]['date']   = $key;
    $final_table[$key]['closed'] = $result->total_closed;
}

第 4 步

现在您可以遍历表来操作数据,从而产生您需要的结果:

$results_table = array();
$active        = $active_before_start;
foreach ($final_table as $key => $item)
{
    $opened = (isset($item['opened']) ? $item['opened'] : 0;
    $closed = (isset($item['closed']) ? $item['closed'] : 0;
    $active = $active + ($opened' - $closed);

    $results_table[$key]['date']   = $key;
    $results_table[$key]['opened'] = $opened;
    $results_table[$key]['closed'] = $closed;
    $results_table[$key]['active'] = $active;
}

从那时起,您始终可以使用ksort 以防万一显示排序后的数组结果。

HTH

【讨论】:

  • 这对一些人有所帮助——至少得到了我需要的大部分输出。非常感谢:) 我认为我实际上要做的只是在数据库中创建一个新表,该表存储基于每天打开/关闭项目的活动计数 - 然后只需查询它。这比获得真正的活跃历史计数要简单得多。
  • 创建一个可用于报告目的的新表格(例如您的表格)绝对是一个好主意。您还可以做的一件事是创建一个脚本,在给定日期范围内重新计算该新表的数据。这样您的数据将始终准确。
  • 我找到了一份旧报告,让我可以填写大部分历史数据。对于未来的日子,我创建了一个存储日期和计数的表 - 创建记录时,它会检查存储的最后日期是否等于当前日期。如果是,它会增加现有计数。如果日期不相等,它会从最近的日期中获取值,将其加一,然后插入具有更新计数的新日期记录。对项目关闭程序还有另一个检查,它做同样的事情,只是递减计数器。感谢您的所有帮助:)
【解决方案3】:

我可以让它告诉我在表中存在这一天的那一天有多少人打开,但我没有想出的是如何让它为一年中的每一天写出一行并给出我是那天的伯爵。

我的理解是:您想计算每个结束日期的问题吗?

SELECT COUNT(*) FROM dates WHERE your_condition GROUP BY DAY_OF_YEAR(close_date)

【讨论】:

  • 不完全-我实际上已经在有效地这样做了。我要做的是生成历史数据——不是每个关闭日期关闭了多少,或者每个关闭日期存在多少,而是一年中的每一天都有多少打开。
  • 好吧,我明白了一点。如果没有人给你,我明天会回来回答。
猜你喜欢
  • 2016-10-02
  • 2014-06-20
  • 1970-01-01
  • 2017-06-03
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多