如何使用PHP转换规范化数据集?

时间:2015-09-04 13:43:48

标签: php mysql pivot normalization

以下是我的表格:

用户表

id   |   name  
1    |   john  
2    |   lucy  

user_accounts表

id   |   user_id    |   account_name
1          2             lucy_lu
2          1             johndoe

account_parameters表

id   |  account_id  |  parameter_id   |  value
1           1              10             4000
2           1              11             1450
3           2              10             5000
4           2              11             1150

参数表

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生成带数据的列”和类似的,找到了1或2个表的许多解决方案,但我不知道如何在这里实现它们。我知道如何选择带连接的静态字段,但我不知道在这个例子中如何选择“高度”和“最高分数”。

2 个答案:

答案 0 :(得分:3)

如果必须使用SQL执行此操作,那么使用编写SQL的PHP​​似乎是最不紧密耦合的方法。

首先,查询参数表并存储在数组中。

然后在三个部分构建您的查询字符串,中间部分是动态创建的。

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


执行该动态构建的查询应该为您提供结果。

您可能需要一些上下文敏感度来确定您在最终结果中执行和不希望包含哪些参数(使用此结构,您似乎总是不想要所有参数)

答案 1 :(得分:2)

由于我做了类似的事情,这里有一些事情可以开始:

$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);

基本上,它与MatBailie

的答案背景相同