MySQL 将某些结果分组到一个数组中

Posted

技术标签:

【中文标题】MySQL 将某些结果分组到一个数组中【英文标题】:MySQL group certain results into an array 【发布时间】:2012-12-13 04:15:01 【问题描述】:

我正在编写一个复杂的 mysql 查询,其中包含多个 LEFT JOINs 来组合来自多个不同表的数据。

$public_query = 
"SELECT * FROM  `wsat_ib` 
LEFT JOIN wp_usermeta ON wsat_ib.user_id = wp_usermeta.user_id
LEFT JOIN wpjb_resume ON wsat_ib.user_id = wpjb_resume.user_id
LEFT JOIN wpjb_field_value ON wpjb_resume.id=wpjb_field_value.job_id 
LEFT JOIN wpjb_application ON wpjb_application.user_id = wsat_ib.user_id
WHERE wp_usermeta.meta_key =  'target_employer'
AND wp_usermeta.meta_value =  'public'
AND wpjb_resume.is_active =1
";

我的问题:表 wp_usermeta 可以为同一个 user_id 包含多行。例如,用户(user_id = 5)在表 wp_usermeta 中可能有不止一行,其字段为:meta_key,即“target_employer”。如果不清楚,行可能如下所示。

id    user_id    meta_key           meta_value
1     5          target_employer    13
2     5          target_employer    53
3     79         target_employer    21

我的问题:有什么方法可以将 wp_usermeta 中的每个匹配行作为数组返回到我的一个结果对象中?所以var_dump() 看起来像这样:

object(stdClass)#2906 (14) 
  ["user_id"]=>
  string(4) "5"
  ["firstname"]=>
  string(6) "Bilbo"
  ["lastname"]=>
  string(3) "Baggins"
  ...
  ["target_employer"]=>
  array(2) 
    [0]=>13,
    [1]=>53
  

更新: @bpannulla:这是真正的(未简化的查询)...

"SELECT wsat_ib.user_id, wpjb_resume.firstname, wpjb_resume.lastname, wsat_ib.overall_score, wsat_ib.account_score, wsat_ib.econ_score, wsat_ib.math_score, wsat_ib.logic_score, wsat_ib.fsanaly_score, wsat_ib.corpval_score, wsat_ib.end_time, GROUP_CONCAT(wp_usermeta.meta_value) AS target_employers, wpjb_field_value.value AS school, wpjb_application.job_id
FROM  `wsat_ib` 
LEFT JOIN wp_usermeta ON wsat_ib.user_id = wp_usermeta.user_id
LEFT JOIN wpjb_resume ON wsat_ib.user_id = wpjb_resume.user_id
LEFT JOIN wpjb_field_value ON wpjb_resume.id=wpjb_field_value.job_id 
LEFT JOIN wpjb_application ON wpjb_application.user_id = wsat_ib.user_id AND wpjb_application.field_id=3
WHERE (wp_usermeta.meta_key =  'target_employer'
AND wp_usermeta.meta_value =  'public'
AND wpjb_resume.is_active =1)
GROUP BY user_id
";

【问题讨论】:

“有什么方法可以将 wp_usermeta 中的每个匹配行作为数组返回到我的结果对象之一中?”不,SQL 要求结果单元格是原子的。没有数组。您可以将同一用户的值累积到一个数组中,使用 user_id 作为键。 @user4035 你能举个例子如何做你描述的事情吗?这听起来像是我想做的事情。 【参考方案1】:

我不认为 MySQL 可以将数组返回给 php,但它可以使用 GROUP_CONCAT aggregate function. 返回一个分隔列表尝试类似:

SELECT user_id, firstname, lastname,
     GROUP_CONCAT(wp_usermeta.meta_value) as target_employer_id
FROM `wsat_ib` 
    LEFT JOIN wp_usermeta ON
        (wsat_ib.user_id = wp_usermeta.user_id
           AND wp_usermeta.meta_key = 'target_employer')
GROUP BY user_id, firstname, lastname

默认情况下,您应该在target_employer_id 中获得一个以逗号分隔的元素列表。您可以使用 PHP explode 函数将其转换为 PHP 逻辑中的数组。

【讨论】:

我几乎已经完成了这项工作,但我正在努力处理GROUP BY。我得到了预期的返回行数,但我对为什么我在 target_employer 字段中得到多个重复感到困惑。尽管我的大多数用户只有一个目标雇主,但我看到每行返回的雇主 ID 介于 1 到 12 个之间。大多数是相同值的重复,这很奇怪,因为 wp_usermeta 表中不允许允许重复的键/值对。有什么建议吗? GROUP_CONCAT 函数需要一些额外的参数,可以在这些情况下提供帮助(请参阅我链接的文档页面)。特别是,尝试GROUP_CONCAT(DISTINCT wp_usermeta.meta_value) 以获得唯一列表。我有点困惑,会有重复,除非你添加了更多的表,并且从连接中得到了成倍的行。 我认为这就是正在发生的事情。我确实在示例中省略了几个表格,以使问题更具可读性。我在问题中添加了真正的查询(上图)。 您在查询的 SELECT 子句中输出的每个字段通常都需要出现在 GROUP BY 子句中,除非您在聚合函数表达式(如 GROUP_CONCAT)中使用它。某些数据库服务器(包括 MySQL)对此有例外,但这是一般规则。将额外的字段添加到 GROUP BY 中,这可能会消除额外的行。因此 SELECT * 查询通常会妨碍使用聚合函数。 这似乎是问题所在。我有额外的SELECTs 导致重复(又名“笛卡尔积”?)。将它们添加到 GROUP BY 修复了该问题。但我有最后一个问题:可以添加第二个GROUP_CONCAT 吗?我正在对其进行测试,它可以工作我以前的问题返回(在 target_employer 字段中重复)。

以上是关于MySQL 将某些结果分组到一个数组中的主要内容,如果未能解决你的问题,请参考以下文章

Pandas —— 数据分组

如何将mysql内部连接结果从行分组到列

结果集成二维数组

将数组拆分为按对象属性分组的 2 个数组 [重复]

根据数字对数组的行进行分组

mysql语法------9----分组函数