2015-09-04 35 views
3

這裏是我的表:如何使用PHP轉換規範化的數據集?

用戶表

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個表,但我不知道如何實現那些這裏。我知道如何選擇帶連接的靜態字段,但我不知道如何在此示例中選擇「高度」和「最高分數」。

+0

什麼回答有關GROUP BY? – jarlh

+0

我認爲user_id 1的高度應該是4000,其他數據也是 –

+0

你使用php嗎? – Alex

回答

3

如果你必須這樣做使用SQL,那麼使用PHP編寫SQL似乎是最不緊密耦合的方法。

首先,查詢您的參數表並將其存儲在數組中。

然後建立三個部分的查詢字符串,中間部分是動態創建的。

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

這是行得通的。但是,我使用MAX而不是SUM。因爲使用SUM,我無法獲取字符串值。謝謝。 – wast

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