我让这个问题听起来比实际上更难。我的解决方案没有直接回答我的问题,尽管它解决了根本问题。
我需要为报告门户生成数据导出,其中有一组定义的变量(例如,名字、姓氏等)+ 随时间变化的数据变量(即,必须根据是否存在包含或排除在定义的时间间隔内)。此外,它必须以 Excel 友好格式(例如 csv)生成(因此第一次尝试使用 GROUP CONCATination 使用逗号)。
我采用的解决方案是动态查询生成。
public function getCombined/*[..]*/ (array $filter = []) {
// Find the columns
$freeform_data = $this->db
->prepare("
SELECT
DISTINCT `dpd1`.`name`
FROM
`device_product` `dp1`
INNER JOIN
`device_product_data` `dpd1`
ON
`dpd1`.`device_product_id` = `dp1`.`id`;
")
->execute([$filter)
->fetchAll(\PDO::FETCH_COLUMN);
$freeform_data_selectors = '';
$freeform_data_join = '';
foreach ($freeform_data as $i => $name) {
if ($name != preg_replace('/[^a-z_-]/i', '', $name)) {
throw new \ErrorException('Invalid freeform data input name ("' . $name . '").');
}
$alias = '`dpd' . ($i + 1) . '`';
$freeform_data_selectors .= ', ' . $alias . '.`value` `freeform_' . $name . '`';
$freeform_data_join .= '
LEFT JOIN
`device_product_data` ' . $alias . '
ON
' . $alias . '.`device_product_id` = `dp1`.`id` AND
' . $alias . '.`name` = \'' . $name . '\'
';
}
$stmt = $this->db
->prepare("
SELECT
`d1`.`mac_address` `device_mac_address`,
{$freeform_data_selectors}
FROM
`device_product` `dp1`
{$freeform_data_join}
GROUP BY
`dp1`.`id`;", [\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false])
->execute($filter);
return stmt;
}
这是一个精简的例子,它可能看起来类似于 Robin Castlin 的建议。但是,实际查询还有另外 10 个连接和一个大型数据集 (2M+)。Castlin 的建议需要更多的资源来检索和组织数据。