【问题标题】:Php mysql join to subarray with field namesphp mysql加入带有字段名的子数组
【发布时间】:2017-10-23 00:26:06
【问题描述】:

我尝试使用 ONE 查询将表连接到具有列名 => 列值的子数组中..

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

user_id   email        ...
1         xxx@xx.xx    ...
2         yyy@yy.yy    ...

短表(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' => xxx@xx.xx,
  'plugin_enter' => 1,
  'offers_view' => 0
),
[1] = array(
  'user_id' => 2,
  'email' => yyy@yy.yy,
  'plugin_enter' => 1,
  'offers_view' => 1,
  ...
),

我只需要像这样输出到子数组中:

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

这可能与 ONE 查询有关吗?

Table2(权限)包含大约 60 列。如果仅与 Table1 连接一行,是否可以使用列值 CONCAT 列的名称?

【问题讨论】:

  • 我认为这在 php 中仅针对一个查询是不可能的
  • 将 table2 更改为 uid、name、value 之类的内容,以避免 60 列和无法维护查询。

标签: php mysql join left-join concat


【解决方案1】:

另一种可能的解决方案是为查询添加前缀。
灵感来自帖子: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' => xxx@xx.xx,
   'prefix_start' => 
   'plugin_enter' => 1,
   'offers_view' => 0
   'prefix_end' => 
)
...

然后简单的 PHP 脚本将 prefix_start 和 prefix_end 之间的所有数组数据添加到自己的子数组中。

【讨论】:

    【解决方案2】:

    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 对的数组,然后将它们转换为 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
    

    【讨论】:

    • 感谢意见,但权限表中并非所有列都具有相同的“结尾”
    • 好的,我展示了另一种方法,它不依赖于遵循特定命名方案的列。它在查询中分配别名。
    • 没有什么可以自动完成。您可以编写一个简单的脚本来从 DDL 创建查询。
    • 我不明白你的问题。是关于我的答案还是关于你在另一个问题中找到的答案?
    • 对不起,不是关于你的答案..我发布了主要问题的新可能解决方案。
    猜你喜欢
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2014-12-17
    • 1970-01-01
    相关资源
    最近更新 更多