左连接重复

时间:2010-06-28 02:27:43

标签: php mysql query-optimization left-join

我需要查询几个表才能获取某个用户的所有行。 表基本上看起来像这样

contact
=======
id_contact PK
firstName
lastName
...

contact_phone
===============
id_contact_phone, PK
id_contact, FK
id_phone_type, FK
phone
...

phone_type
============
id_phone_type PK
phone_type
....

除了用于emailphone之外,还有一堆类似于那些的表。我需要显示给定联系人的所有信息,我使用了几个{{1}但我不确定如何输出信息。

这是我的查询

LEFT JOIN

我的问题是,如果某个联系人有多个电话号码,电子邮件等,查询显然会返回超过1行,所以我不确定如何显示信息,因为大多数列都是重复的其他。以下是该查询可能返回的示例

SELECT contact.id_contact, contact.lastName, contact.firstName, contact_email.email, email_type.email_type, contact_phone.phone, phone_type.phone_type, contact_company.contact_title, company.company_name
FROM contact 
    LEFT JOIN contact_email
        ON contact.id_contact = contact_email.id_contact
    LEFT JOIN email_type 
        ON contact_email.id_email_type = email_type.id_email_type
    LEFT JOIN contact_phone
        ON contact.id_contact = contact_phone.id_contact
    LEFT JOIN phone_type
        ON contact_phone.id_phone_type = phone_type.id_phone_type
    LEFT JOIN contact_company
        ON contact.id_contact = contact_company.id_contact
    LEFT JOIN company
        ON contact_company.id_company = company.id_company
WHERE contact.id_contact = $cid

如何在没有冗余数据的情况下在php中显示信息,我的查询能够进行优化吗?

4 个答案:

答案 0 :(得分:0)

mysql有一个很棒的group_concat函数。结合GROUP BY id_contact`,这将做你想要的。以你的例子:

SELECT contact.id_contact, contact.lastName, contact.firstName,
    GROUP_CONCAT(CONCAT(contact_email.email, ' : ', email_type.email_type) SEPARATOR ', ') AS email,
    GROUP_CONCAT(CONCAT(contact_phone.phone, ' : ', phone_type.phone_type) SEPARATOR ', ') AS phone,
    contact_company.contact_title, company.company_name
FROM contact 
    LEFT JOIN contact_email
        ON contact.id_contact = contact_email.id_contact
    LEFT JOIN email_type 
        ON contact_email.id_email_type = email_type.id_email_type
    LEFT JOIN contact_phone
        ON contact.id_contact = contact_phone.id_contact
    LEFT JOIN phone_type
        ON contact_phone.id_phone_type = phone_type.id_phone_type
    LEFT JOIN contact_company
        ON contact.id_contact = contact_company.id_contact
    LEFT JOIN company
        ON contact_company.id_company = company.id_company
WHERE contact.id_contact = $cid

请注意,我从未在正常的CONCAT周围使用GROUP_CONCAT,但我认为没有理由说它不起作用。

答案 1 :(得分:0)

如果您的电子邮件和手机类型一致,则可以通过将不同类型作为投影列返回来将其展平为一行,例如,对于电子邮件类型:

SELECT contact.id_contact, contact.lastName, contact.firstName,
  contact_company.contact_title, company.company_name, work_email.email AS work_email,
  personal_email.email as personal_email, mobile_phone.phone as mobile_phone,
  work_phone.phone as work_phone
FROM contact 
  LEFT JOIN contact_email AS work_email
    ON (contact.id_contact = work_email.id_contact AND 
      work_email.id_email_type = email_type.id_email_type AND
      email_type.email_type = 'Work')
  LEFT JOIN contact_email AS personal_email
    ON (contact.id_contact = personal_email.id_contact AND 
      personal_email.id_email_type = email_type.id_email_type AND
      email_type.email_type = 'Personal')
  LEFT JOIN contact_phone AS mobile_phone
    ON (contact.id_contact = mobile_phone.id_contact AND 
      mobile_phone.id_phone_type = phone_type.id_phone_type AND
      phone_type.phone_type = 'Mobile')
  LEFT JOIN contact_phone AS work_phone
    ON (contact.id_contact = work_phone.id_contact AND 
      work_phone.id_phone_type = phone_type.id_phone_type AND
      phone_type.phone_type = 'Work')
WHERE contact.id_contact = $cid

答案 2 :(得分:0)

如果您有不一致/未知数量的电子邮件或电话号码等,那么您最好通过多个select语句检索数据。这完全取决于您希望如何使用Web服务器端的数据。可能的是,你实际上并不需要这种表格格式。

如果您担心运行多个查询的性能,请记住您有时可以在一个查询中放置多个语句并返回多个结果集。我不知道这是否可以用PHP做,但我认为是。

答案 3 :(得分:0)

由于类型未知,您可以通过在PHP上的类似问题中扩展另一个答案来在PHP方面使用某些分组:Grouping Records from While Loop

首先请确保您在id_contact上订购并在查询中输入内容:

...
WHERE contact.id_contact = $cid
ORDER BY contact.id_contact, email_type.email_type, phone_type.phone_type

然后在循环显示结果行时对行显示进行手动分组:

$contact_id = 0;
while($row = mysql_fetch_array($result))
{
    if( $row['contact_id'] != $contact_id)
    {
        echo '<hr><br><h3>Contact: ' . $row['first_name'] . $row['last_name']  . '</h3>';
        $contact_id= $row['contact_id'];
        $phone_type = null;
        $email_type = null;
    }
    if ($row['email_type] != $email_type)
    {
       echo $row['email_type'] . ' Email: ' . $row['email'];
       $email_type = $row['email_type']
    }
    if ($row['phone_type] != $phone_type)
    {
       echo $row['phone_type'] . ' Phone: ' . $row['phone'];
       $phone_type = $row['phone_type']
    }
}
相关问题