如何从mysql多对多选择中将单个值分组为数组?

时间:2019-03-04 21:59:15

标签: mysql sql

我有三个表,一个用于业务列表,一个用于Dining_types,一个用于Dining_listing_types。

business_listings:

 +--------+------------------+------------------+
 |  id    |  business_type   |   business_name  |
 +--------+------------------+------------------+
 |  1     |       1          |   china house    |
 +--------+------------------+------------------+

dining_listing_types:

 +--------+------------------+------------------+
 |  id    |    listing_id    |    type_id       |
 +--------+------------------+------------------+
 |   1    |        1         |        1         |
 +--------+------------------+------------------+
 |   2    |        1         |        3         |
 +--------+------------------+------------------+

dining_types:

 +--------+------------------+
 |  id    |      type        |
 +--------+------------------+
 |  1     |   Asian          |
 +--------+------------------+
 |  2     |   Italian        |
 +--------+------------------+
 |  3     |   Chinese        |
 +--------+------------------+

如您所见,列表可以具有多种类型,其中Dining_listing_types表用作“中间人”表。

但是,当我尝试对查询使用联接时,我会获得两条记录

SELECT bl.id AS id, bl.business_name AS name, dt.type AS type
FROM business_listings bl 
JOIN dining_listing_types dlt ON bl.id = dlt.listing_id 
JOIN dining_types dt ON dlt.type_id = dt.id

结果:

 array(2) { [0]=> object(stdClass)#7 (3) { ["id"]=> string(1) "1" ["name"]=> 
 string(23) "China House" ["type"]=> string(5) "Asian" } [1]=> 
 object(stdClass)#8 (3) { ["id"]=> string(1) "1" ["name"]=> string(23) "China 
 House" ["type"]=> string(18) "Chinese" } }

我不想要那样。我尝试了GROUP BY bl.id,但又找回了一条记录,但又丢失了另一种记录:

SELECT bl.id AS id, bl.business_name AS name, dt.type AS type
FROM business_listings bl 
JOIN dining_listing_types dlt ON bl.id = dlt.listing_id 
JOIN dining_types dt ON dlt.type_id = dt.id
GROUP BY bl.id

结果:

 array(1) { [0]=> object(stdClass)#7 (3) { ["id"]=> string(1) "1" ["name"]=> 
 string(23) "China House" ["type"]=> string(5) "Asian" } }

我想要的结果:

array(1) { [0]=> object(stdClass)#7 (3) { ["id"]=> string(1) "1" ["name"]=> 
string(23) "China House" ["type"]=> array(2) ["Asian", "Chinese"] } }

2 个答案:

答案 0 :(得分:0)

@rickdenhaan评论说,GROUP_CONCAT()似乎与您要寻找的非常接近。这不会生成type的数组,而是一个逗号分隔的列表。另一个不错的选择是生成一个JSON数组,但是我不确定这是否真的会有所帮助。

要使此功能按预期工作,您需要将business_name添加到非聚合列的列表中:

SELECT bl.id AS id, bl.business_name AS name, GROUP_CONCAT(dt.type) AS types
FROM business_listings bl 
INNER JOIN dining_listing_types dlt ON bl.id = dlt.listing_id 
INNER JOIN dining_types dt ON dlt.type_id = dt.id
GROUP BY bl.id, bl.business_name

NB:如@spencer7593所评论,如果我们需要返回与LEFT JOIN不相关的INNER JOIN,则最好使用business_listings而不是dining_types {{1}}。

答案 1 :(得分:0)

根据您的输出数据,我假设您正在使用PHP。如果您使用的是mysqli类(具有连接$conn),则可以使用类似的方法(使用@rickdenhaan建议的GROUP_CONCAT)来实现所需的目标:

$sql = 'SELECT bl.id AS id, bl.business_name AS name, GROUP_CONCAT(dt.type) AS type
FROM business_listings bl 
LEFT JOIN dining_listing_types dlt ON bl.id = dlt.listing_id 
LEFT JOIN dining_types dt ON dlt.type_id = dt.id
GROUP BY bl.id, bl.business_name';
$result = $conn->query($sql) or die($conn->error);
while ($obj = $result->fetch_object()) {
    $obj->type = explode(',', $obj->type);
    // do something with $obj
}