仅显示一次数据


Display data only once

我为日托中心的父母创建了一个联系人列表。现在我希望在网页上显示它。到目前为止,它在技术上工作得很好,但这是我不满意的布局。

我的数据库如何工作:每个父母可以有一个或多个孩子,每个孩子可以有一个或多个父母 - 多对多关系。我把它分解成三张桌子——父母、孩子和parent_children,以建立一对多的关系。然后我使用了 JOIN,一切都显示得很好。但是,由于它显示每个实体,因此在网页上显示它变得相当混乱。我将用一个例子来解释:

家庭1:马克和爱丽丝威尔逊有两个孩子,约翰和比尔。
家庭2:彼得和杰西卡·罗伯逊有一个孩子,丽莎。

Current layout:
Parent                Child
-------------------------------
Mark Wilson           John Wilson
Mark Wilson           Bill Wilson
Alice Wilson          John Wilson
Alice Wilson          Bill Wilson
Peter Robertson       Lisa Robertson
Jessica Robertson     Lisa Robertson
-------------------------------
Desired layout:
Parent                Child
-------------------------------
Mark Wilson           John Wilson
Alice Wilson          Bill Wilson
Peter Robertson       Lisa Robertson
Jessica Robertson
-------------------------------

有什么好方法可以获得所需的布局吗?


好的,所以现在我已经让它在一列中工作,具体取决于我如何使用GROUP_CONCAT:

法典:

SELECT GROUP_CONCAT(parents.name) AS Parents, children.name
FROM parents p
LEFT JOIN parents_children pc USING(id_parent)
LEFT JOIN children c USING(id_child)
GROUP BY pc.id_parent;

结果:

Parents                             Children
-----------------------------------------------
Mark Wilson, Alice Wilson           Bill Wilson
Mark Wilson, Alice Wilson           John Wilson
Peter Robertson, Jessica Robertson  Lisa Robertson

同样,如果我GROUP_CONCAT children.name 并按pc.id_child分组,我会得到:

Parents                Children
------------------------------------------
Mark Wilson            Bill Wilson, John Wilson
Alice Wilson           Bill Wilson, John Wilson
Peter Robertson        Lisa Robertson
Jessica Robertson      Lisa Robertson

我真的想要这些的组合,结果如下:

Parents                                Children
----------------------------------------------------
Mark Wilson, Alice Wilson              Bill Wilson, John Wilson
Peter Robertson, Jessica Robertson     Lisa Robertson

SELECT DISTINCT 应将它们限制为父表中每个实体的一个实例。

SELECT
    Parents
  , GROUP_CONCAT(name ORDER BY name) AS Children
FROM
  ( SELECT 
        GROUP_CONCAT(p.id_parent ORDER BY p.name) AS parents_ids
      , GROUP_CONCAT(p.name ORDER BY p.name) AS Parents
      , pc.id_child
      , c.name
    FROM parents p 
      JOIN parents_children pc USING(id_parent)
      JOIN children c USING(id_child)
    GROUP BY pc.id_child
  ) AS tmp 
GROUP BY parents_ids ;

您可以在以下位置进行测试:SQL-Fiddle

表父项:

CREATE TABLE `parents` (

id_part int(11( 不为空AUTO_INCREMENT, parent varchar(60( 默认空, 主键 ( id_part (( 引擎=InnoDB AUTO_INCREMENT=7 默认字符集=UTF8

表子项:

CREATE TABLE `child` (

id_child int(11( 不为空AUTO_INCREMENT, child varchar(60( 默认为空, f_name int(11( 默认空, m_name int(11( 默认空, 主键 ( id_child (, 钥匙m_key ( m_name (, 钥匙f_key ( f_name (, 外键f_key(f_name(引用的约束parents(id_part(在更新级联上删除级联, 外键m_key约束 ( m_name ( 引用 parents ( id_part ( 在更新级联上删除级联( 引擎=InnoDB AUTO_INCREMENT=8 默认字符集=UTF8

查询以联接两个表

SELECT DISTINCT

GROUP_concat(儿童.儿童(,p1.父母,p2.父级从孩子内联接父项 作为 p1 上 p1.id_part = child.f_name内部联接父项 作为 p2 在 p2.id_part = child.m_name分组依据p1.父母,p2.父级

结果

孩子的名字 | 父亲的名字 | 母亲的名字

x,y,z | 父亲 1 | 母亲 1

Q,R | 父亲 2 | 母亲 2

T,J | 父亲 3 | 母亲 3

此问题有两种解决方案:

  1. 在 php 端遍历数组并创建一个数组,其中 [$parent_1 . '|' . $parent2]
    包含另一个带有子项的数组。

  2. 在SQL端做类似的事情:

    SELECT 
        GROUP_CONCAT(Parents.name ORDER BY Parents.parents_id, '|') AS parents, 
        Children.name as child
    FROM Children 
        LEFT JOIN CildrentParents USING( children_id )
        LEFT JOIN Parents USING( parent_id )
    GROUP BY Childrent.children_id
    

    ,然后使用此数据集。

附言我不明白,如何将DISTINCT添加到原始查询中,可以解决这个问题......也许我在这里错过了一些东西。

更新

究竟是什么阻止您使用 PHP 创建一个数组,其中每个 parent 键都包含一个子项列表?