在 MySQL 或 PHP 中连接多行

Posted

技术标签:

【中文标题】在 MySQL 或 PHP 中连接多行【英文标题】:Concatenate multiple rows in MySQL or PHP 【发布时间】:2021-07-15 15:48:09 【问题描述】:

我需要根据中间和子 id 两列的匹配将多行合并为一行。

mid parent sub org item price dsc1 dsc2
216 1 Apple
217 216 1 iPhone $500
218 216 217 1 iPhone PLUS $600
219 216 1 MacBook $900
220 216 219 1 MacBook Pro $1200

我需要这个输出,记下上面的粗体id,带有null sub的项目是base,subtype在后面:

 Apple $500 iPhone $600 iPhone PLUS
 Apple $900 MacBook $1200 MacBook Pro 

我尝试使用 group concat 但它无法正常工作 https://phpize.online/?phpses=501d07429d08ce3d3092f555d9d6367a&sqlses=c40160db7e24f450d3055397db86aeda&php_version=php8&sql_version=mysql57

另一种选择是如上所述显示多行,然后如果有人知道如何操作,则与 PHP 连接:

select top.item, base.mid, base.sub, base.price, base.item from menu base, menu top 
where top.mid = base.parent and base.parent is not null;

【问题讨论】:

【参考方案1】:

您可以使用 MySQL 自连接来做到这一点:

<?php
$stmt = $pdo->query("
SELECT
  `parent_menu`.`item` as `parent_item`,
  `menu`.`price`,
  `menu`.`item`,
  `sub_menu`.`price` as `sub_item_price`,
  `sub_menu`.`item` as `sub_item`
FROM
    `menu`
-- Join the parent brands in if there are any
JOIN
    `menu` as `parent_menu`
ON
    `menu`.`parent` = `parent_menu`.`mid`
-- Join in the subs
JOIN
    `menu` as `sub_menu`
ON
    `menu`.`mid` = `sub_menu`.`sub`");
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) 
    echo implode(' ', $row) . "\n";

Try Me Online

解释:

我们的主要选择语句旨在选择 mids、iPhone 和 MacBook。

所有 mid 都有一个父节点,因此我们可以在主表中的 parent 字段等于父菜单连接中的 mid 字段的情况下内部连接 ​​menu 表。这为我们提供了每个 mid 的 menu_item 值(品牌名称)。

然后我们可以在菜单表上进行另一个内部连接来选择子项目的价格和名称。

最后,通过选择\PDO::FETCH_ASSOC,我们将得到一个如下所示的数组:

[
  'parent_item' => 'Apple',
  'price' => '$500',
  'item' => 'iPhone ',
  'sub_item_price' => '$600',
  'sub_item' => 'iPhone Plus',
]

【讨论】:

非常感谢。一些条目只有基本产品,而其他条目可能有 3 个或更多子类型。我认为这段代码不起作用 - 我有类似的东西......phpize.online/… 例如这个 group_concat 工作得有些好,但它忽略了只有一种产品的类别,我无法解决它\select top.item, group_concat(concat(base.price,' '), base.item, concat(sub.price,' '), sub.item separator ''), base.dsc1, base.dsc2 from menu sub join menu base on sub.sub = base.mid join menu top on sub.parent = top.mid where base.mid=sub.sub group by top.item, base.item @stefan999 在这种情况下,将查询拆分为每个级别的两个或三个单独的查询,或者考虑不需要递归自联接的不同数据库架构,您可能会更幸运.但是,如果需要递归自连接,您可以在此线程 dba.stackexchange.com/questions/46127/recursive-self-joins 中找到有关如何执行此操作的更多信息 其实,如果只有 3 层深,你可以这样做:phpize.online/… 很好,但是第 2 行是重复的 - 900 美元的 iPhone 红色应该是第 3 项或第 1 行中的最后一项...您可以尝试使用上面的代码吗(我无法弄清楚我我的代码中缺少)【参考方案2】:

评论太长了:

我看不出以下数据集与您在上面发布的内容有何一致。

+=====+========+========+=====+=============+========+========+========+
| mid | parent | sub    | org | item        | price  | dsc1   | dsc2   |
+=====+========+========+=====+=============+========+========+========+
| 1   | (null) | (null) | 1   | Apple       | (null) | (null) | (null) |
+-----+--------+--------+-----+-------------+--------+--------+--------+
| 2   | 1      | (null) | 1   | iPhone      | $1000  | (HI)   | (null) |
+-----+--------+--------+-----+-------------+--------+--------+--------+
| 3   | 1      | 2      | 1   | iPhone Plus | $1221  | (HI)   | (null) |
+-----+--------+--------+-----+-------------+--------+--------+--------+
| 4   | 1      | 2      | 1   | iPhone Red  | $1600  | (HI)   | (null) |
+-----+--------+--------+-----+-------------+--------+--------+--------+
| 5   | 1      | (null) | 1   | iMac        | $900   | (HI)   | (null) |
+-----+--------+--------+-----+-------------+--------+--------+--------+

【讨论】:

所以是3级数据。 1 级 - 1 行是一个类别(没有父 id),2 级是基本产品级别(父 id 对应于类别的中间),第 3 级是一个基本产品的品种(由对应的非空子 id 标识到基本产品的中间) 但是上面的数据集中没有'216'

以上是关于在 MySQL 或 PHP 中连接多行的主要内容,如果未能解决你的问题,请参考以下文章

mysql连接查询

MySQL - 在一个字段中显示多行(具有内部连接的表)q

Mysql - 连接 - 返回太多行 - 每个连接表一个,但不想要那个

在 MySQL 中将多行连接成单行

MySql - 使用连接子查询插入多行?

MySQL 将多行作为列连接