6

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

+------------------------+
| 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 处理所有查询 - 我相当确定我可以将所有查询数据从单个查询写入单个数组,然后循环通过它来构建报告,但我真的不希望这样做。有什么建议么?

4

3 回答 3

0

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

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

SELECT COUNT(*) FROM dates WHERE your_condition GROUP BY DAY_OF_YEAR(close_date)
于 2012-09-07T14:12:00.550 回答
0

仅使用 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以防万一显示排序后的数组结果。

高温高压

于 2012-09-07T15:00:06.953 回答
0

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

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

  • 记录数 >= 日期范围之间的日期数
  • id-s 必须连续到 daterange 之间的日期数

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

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
;
于 2012-09-07T18:48:40.307 回答