2017-05-23 30 views
2

我尝试加入使用一个查询与列名=>列值的子阵列表..PHP的MySQL加入与字段名称子阵列

短表(1)“用户”结构数据:

user_id email  ... 
1   [email protected] ... 
2   [email protected] ... 

短表(2) “users_permissions” 与数据结构:

user_id plugin_enter offers_view ... 
1   1    0    ... 
2   1    1    ... 

如果我使用经典方法 - 联接左

SELECT `uperms`.*, `u`.* 
FROM (`users` as u) 
LEFT JOIN `users_permissions` as uperms ON `u`.`user_id` = `uperms`.`user_id` 

我得到经典的输出

[0] = array(
    'user_id' => 1, 
    'email' => [email protected], 
    'plugin_enter' => 1, 
    'offers_view' => 0 
), 
[1] = array(
    'user_id' => 2, 
    'email' => [email protected], 
    'plugin_enter' => 1, 
    'offers_view' => 1, 
    ... 
), 

所有我需要的是输出到子阵就象这样:

[0] = array(
    'user_id' => 1, 
    'email' => [email protected], 
    'permissions => array(
     'plugin_enter' => 1, 
     'offers_view' => 0 
), 
), 
... 

这是可以做到使用一个查询?

表2(权限)包含大约60列。如果加入Table1只有一行,是否可以用列值CONCAT列名?

+0

我认为这是不可能在PHP只有一个查询 – Chinito

+0

更改您的table2到像uid,名称,价值,以避免60 colums和不可能维护查询。 –

回答

1

MySQL没有数组或嵌套结构,所以无法在SQL中执行此操作。

更改您的查询,让您从users_permissions的所有字段具有一致的命名风格。然后,您可以使用PHP循环将所有与其匹配的数组元素都收集到permissions数组中。

查询:

SELECT u.*, up.plugin_enter AS perm_plugin_enter, up.offers_view AS perm_offers_view, ... 
FROM users AS u 
JOIN users_permissions AS up ON u.user_id = up.user_id 

PHP:

foreach ($all_results as &$row) { 
    $permissions = array(); 
    foreach ($row as $key => $value) { 
     if (strpos($key, 'perm_') === 0) { 
      $permission[substr($key, 5)] = $value; 
      unset($row[$key]); 
     } 
    } 
    $row['permissions'] = $permissions; 
} 

您可以通过连接所有的列名和值在表中做到这一点:

SELECT u.*, CONCAT_WS(',', CONCAT('plugin_enter:', plugin_enter), CONCAT('offers_view:', offers_view), ...) AS permissions 
FROM users AS u 
JOIN users_permissions AS up ON u.user_id = up.user_id 

然后你的PHP代码使用explode()$row['permissions']分成name:value对数组,并且t母鸡将它们转换为PHP数组中的key=>value

另一个解决方案是重新设计你的users_permissions表:

user_id permission_type value 
1  plugin_enter 1 
1  offers_view  0 
... 
2  plugin_enter 1 
2  offers_view  1 
... 

然后你就可以查询:

SELECT u.*, GROUP_CONCAT(permission_type, ':', value) AS permission 
FROM users AS u 
JOIN users_permissions AS up on u.user_id = up.user_id 
+0

感谢您的意见,但权限表并不是所有的列都有相同的“结尾” – drozdo

+0

好的,我展示了另一种方法,它不依赖于特定命名方案后面的列。它在查询中分配别名。 – Barmar

+0

fuuh 60列?它写得太多.. – drozdo

0

另一种可能sollution是添加前缀进行查询。
邮寄启发:https://stackoverflow.com/a/9926134/2795923

SELECT `u`.*, ':prefix_start:', `uperms`.*, ':prefix_end:' 
FROM (`users` as u) 
LEFT JOIN `users_permissions` as uperms ON `u`.`user_id` = `uperms`.`user_id` 

输出数组是这样的:

[0] => array(
    'user_id' => 1 
    'email' => [email protected], 
    'prefix_start' => 
    'plugin_enter' => 1, 
    'offers_view' => 0 
    'prefix_end' => 
) 
... 

那么容易的PHP脚本prefix_start之间添加所有阵列数据和prefix_end到自己的子阵。