如何使用 PHP 转换归一化数据集?
How to transform a normalised data set using PHP?
这是我的 tables:
用户table
id | name
1 | john
2 | lucy
user_accounts table
id | user_id | account_name
1 2 lucy_lu
2 1 johndoe
account_parameters table
id | account_id | parameter_id | value
1 1 10 4000
2 1 11 1450
3 2 10 5000
4 2 11 1150
参数table
id | parameter_value | parameter_name
10 height Height
11 max_score Max Score
我要得到结果:
user_id | user_name | account_name | Height | Max Score
1 john johndoe 5000 1150
2 lucy lucy_lu 4000 1450
我搜索了 "mysql generate columns with data" 和类似内容,找到了 1 或 2 table 的许多解决方案,但我不知道如何在此处实施这些解决方案。我知道如何 select 带连接的静态字段,但我不知道如何 select "Height" 和 "Max Score" 在这个例子中。
如果您必须 使用 SQL 执行此操作,那么使用 PHP 写入 SQL 似乎是最不紧密耦合的方法。
首先,查询您的参数 table 并存储在一个数组中。
然后分三部分构建查询字符串,中间部分是动态创建的。
SELECT
user_accounts.user_id AS user_id,
user.name AS user_name,
user_accounts.account_name AS account_name,
对数组中的每条记录重复此操作 (来自 parameters
)。
SUM(
CASE WHEN account_parameters.parameter_id = @param_id
THEN account_parameters.value
END
) AS @param_name,
使用 PHP 替换 @param_id 和 @param_name 值。
(注意逗号,您不希望 SQL 的最后一行出现逗号。)
FROM
account_parameters
INNER JOIN
user_accounts
ON user_accounts.id = account_parameters.account_id
INNER JOIN
user
ON user.id = user_accounts.user_id
GROUP BY
user_accounts.user_id,
user.name,
user_accounts.account_name
注意:在MySQL中你真的只需要GROUP BY user_accounts.user_id
,但我不推荐ab一般使用该功能。
执行该动态构建的查询应该为您调整结果。
您可能需要一些上下文敏感性来确定您想要和不想包含在最终结果中的参数(使用这种结构,您似乎并不总是需要所有参数).
因为我做了类似的事情,这里有一些开始:
$parameters = array(
array("id" => 10, "parameter_value" => "height", "parameter_name" => "Height"),
array("id" => 11, "parameter_value" => "max_score", "parameter_name" => "Max Score")
); //fetch all parameters from your parameters table
//specify the table where the values are stored
$tableName = 'account_parameters';
//specify the column name in this table where the identifier for your data lies
$dataIdColumnName = 'account_id';
//set the first column up, which holds your datakey
$selectPivotFields = array("`".$tableName."`.`".$dataIdColumnName."`");
//loop over all parameters
if(is_array($parameters))
for($i=0;$i<count($parameters);$i++)
{
//build a part of your pivot query
$selectPivotFields[] = sprintf("MAX(IF(`%1$s`.`parameter_id` = '%2$d', `%1$s`.`value`, NULL)) AS `%3$s`", $tableName, $parameters[$i]['id'], $parameters[$i]['parameter_value']);
}
//build the actual query for readability i simplified it a little bit
$sql = sprintf("
SELECT
%1$s
FROM
`%2$s`
WHERE
`%2$s`.`%3$s` = '%4$d'
GROUP BY
`%2$s`.`%3$s`
", implode(", ", $selectPivotFields), $tableName, $dataIdColumnName, $dataId);
//and execute your query with the prefered class
$result = execute($sql);
基本上,它与
的答案的背景相同
这是我的 tables:
用户table
id | name
1 | john
2 | lucy
user_accounts table
id | user_id | account_name
1 2 lucy_lu
2 1 johndoe
account_parameters table
id | account_id | parameter_id | value
1 1 10 4000
2 1 11 1450
3 2 10 5000
4 2 11 1150
参数table
id | parameter_value | parameter_name
10 height Height
11 max_score Max Score
我要得到结果:
user_id | user_name | account_name | Height | Max Score
1 john johndoe 5000 1150
2 lucy lucy_lu 4000 1450
我搜索了 "mysql generate columns with data" 和类似内容,找到了 1 或 2 table 的许多解决方案,但我不知道如何在此处实施这些解决方案。我知道如何 select 带连接的静态字段,但我不知道如何 select "Height" 和 "Max Score" 在这个例子中。
如果您必须 使用 SQL 执行此操作,那么使用 PHP 写入 SQL 似乎是最不紧密耦合的方法。
首先,查询您的参数 table 并存储在一个数组中。
然后分三部分构建查询字符串,中间部分是动态创建的。
SELECT
user_accounts.user_id AS user_id,
user.name AS user_name,
user_accounts.account_name AS account_name,
对数组中的每条记录重复此操作 (来自 parameters
)。
SUM(
CASE WHEN account_parameters.parameter_id = @param_id
THEN account_parameters.value
END
) AS @param_name,
使用 PHP 替换 @param_id 和 @param_name 值。
(注意逗号,您不希望 SQL 的最后一行出现逗号。)
FROM
account_parameters
INNER JOIN
user_accounts
ON user_accounts.id = account_parameters.account_id
INNER JOIN
user
ON user.id = user_accounts.user_id
GROUP BY
user_accounts.user_id,
user.name,
user_accounts.account_name
注意:在MySQL中你真的只需要GROUP BY user_accounts.user_id
,但我不推荐ab一般使用该功能。
执行该动态构建的查询应该为您调整结果。
您可能需要一些上下文敏感性来确定您想要和不想包含在最终结果中的参数(使用这种结构,您似乎并不总是需要所有参数).
因为我做了类似的事情,这里有一些开始:
$parameters = array(
array("id" => 10, "parameter_value" => "height", "parameter_name" => "Height"),
array("id" => 11, "parameter_value" => "max_score", "parameter_name" => "Max Score")
); //fetch all parameters from your parameters table
//specify the table where the values are stored
$tableName = 'account_parameters';
//specify the column name in this table where the identifier for your data lies
$dataIdColumnName = 'account_id';
//set the first column up, which holds your datakey
$selectPivotFields = array("`".$tableName."`.`".$dataIdColumnName."`");
//loop over all parameters
if(is_array($parameters))
for($i=0;$i<count($parameters);$i++)
{
//build a part of your pivot query
$selectPivotFields[] = sprintf("MAX(IF(`%1$s`.`parameter_id` = '%2$d', `%1$s`.`value`, NULL)) AS `%3$s`", $tableName, $parameters[$i]['id'], $parameters[$i]['parameter_value']);
}
//build the actual query for readability i simplified it a little bit
$sql = sprintf("
SELECT
%1$s
FROM
`%2$s`
WHERE
`%2$s`.`%3$s` = '%4$d'
GROUP BY
`%2$s`.`%3$s`
", implode(", ", $selectPivotFields), $tableName, $dataIdColumnName, $dataId);
//and execute your query with the prefered class
$result = execute($sql);
基本上,它与