我正在研究应用程序生成构建和MySQL / PHP中的燃尽图表,我用它来生成NVD3.js
下面的代码循环播放我的数据集的最小到最大日期的每一天,可以过滤。
到目前为止,我每天都会运行1次查询,我意识到这可能会增加大量延迟,等待加载大约需要10秒。
如何更快地生成此数据?
调用代码
public function burnupAction()
{
$actionItemTable = $this->getActionItemTable();
$burnUp = array('TotalActionItems' => $actionItemTable->getBurnup('AssignedDate'),
'ECDItems' => $actionItemTable->getBurnup('ECD'),
'OriginalDueItems' => $actionItemTable->getBurnup('DueDate'),
'ActualOpenItems' => $actionItemTable->getBurnup('ClosedDate'));
$this->response->setContent(json_encode($burnUp));
return $this->response;
}
构建图表代码
for ($y = $minYear; $y <= $maxYear; $y++)
{
if ($y == $minYear)
$startMonth = $minMonth;
else
$startMonth = 1;
if ($y == $maxYear)
$finishMonth = $maxMonth;
else
$finishMonth = 12;
for ($m = $startMonth; $m <= $finishMonth; $m++)
{
if ($m < 10)
{
$month = "0$m";
}
else
{
$month = "$m";
}
$monthStr = $this->getMonth($m);
for ($d = 1; $d <= 31; $d++)
{
if ($d< 10)
{
$day = "0$d";
}
else
{
$day = "$d";
}
$dt = "$monthStr $day $y";
$start = "$y-$month-$day";
$end = "$y-$month-$day";
$where = $this->filterString();
$filtered = "SELECT * FROM actionitems " . $where;
if ($field == 'AssignedDate')
{
array_push($subsel, "(select '$dt' as AssignedDate, sum(case when AssignedDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'ECD')
{
array_push($subsel, "(select '$dt' as ECD, sum(case when ECD Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'DueDate')
{
array_push($subsel, "(select '$dt' as DueDate, sum(case when DueDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
if ($field == 'ClosedDate')
{
array_push($subsel, "(select '$dt' as ClosedDate, sum(case when ClosedDate Between '$start' and '$end' then 1 else 0 end) as 'NumActionItems' from ($filtered) s)");
}
}
}
}
if (count($subsel) == 0)
return array();
$sub = join(" union all ", $subsel);
if ($field == 'AssignedDate')
{
$sql = "select AssignedDate, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'ECD')
{
$sql = "select ECD, NumActionItems as ECDItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'DueDate')
{
$sql = "select DueDate, NumActionItems as OriginalDueItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
if ($field == 'ClosedDate')
{
$sql = "select ClosedDate, NumActionItems as AcutalClosedItems, (@csum:= @csum + NumActionItems) as TotalActionItems from ($sub) t";
}
生成的购物车(顶部积聚/底部燃尽)
答案 0 :(得分:1)
您的查询的主要部分是:
SELECT 'Mar 01 2015' AS AssignedDate,
Sum(CASE
WHEN assigneddate BETWEEN '2015-03-01' AND '2015-03-01'
THEN 1
ELSE 0
end) AS 'NumActionItems'
FROM (SELECT *
FROM actionitems) s;
此查询有一个缺点:每个日期都会扫描表格操作项。
为了改善这一点,查询可以写成:
SELECT 'Mar 01 2015' AS AssignedDate,
COUNT(*) AS 'NumActionItems'
FROM actionitems
WHERE assigneddate BETWEEN '2015-03-01' AND '2015-03-01';
这仍然不漂亮,因此需要下一步: 所有日期的替代方案可以是:
SELECT assigneddate,
COUNT(*) AS 'NumActionItems'
FROM actionitems
WHERE assigneddate BETWEEN '2015-03-01' AND '2015-03-30'
GROUP BY assigndate;
这会给你“NumActionItems&#39;每个日期。
将@csum添加为外部查询:
SELECT assigneddate,
( @csum := @csum + numactionitems ) AS TotalActionItems
FROM ( SELECT assigneddate,
COUNT(*) AS 'NumActionItems'
FROM actionitems
WHERE assigneddate BETWEEN '2015-03-01' AND '2015-03-30'
GROUP BY assigndate) a
应该给出相同的结果。
同时添加索引:
CREATE INDEX idx_ai_nn_1 ON actionitems(assigneddate);
如果您扫描表格的日期范围是&lt;&lt;小于您选择的行数。