Осталось объединить дубликаты - PullRequest
1 голос
/ 28 июня 2010

У меня есть несколько таблиц, которые мне нужно запросить, чтобы получить все строки для определенного пользователя.Таблицы в основном выглядят так:

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
....

И есть несколько таблиц, похожих на те, за исключением того, что они предназначены для email, phone и т. Д. Мне нужно отобразить всю эту информацию для данного контакта, яЯ использую несколько LEFT JOIN, но я не уверен, как выводить информацию.

Это мой запрос

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

Моя проблема в том, что если у определенного контакта есть несколько телефонных номеров, электронные письма и т. д. запрос, очевидно, вернет более 1 строки, поэтому я не совсем уверен, как отобразить информацию, так как большинство столбцов будут дубликатами друг друга.Вот пример того, что может вернуть этот запрос

+===========================================================================================+  
| id_contact | lastName | firstName | email            | email_type |  phone   | phone_type |
+===========================================================================================+
| 1          | Doe      | John      | john.doe@123.com | Work       | 555-1234 | Work       |
+------------+----------+-----------+------------------+------------+----------+------------+  
| 1          | Doe      | John      | john.doe@123.com | Work       | 555-2222 | Mobile     | 
+-------------------------------------------------------------------+----------+------------+
| 1          | Doe      | John      | jdoe@email.com   | Personal   | 555-1234 | Work       | 
+------------+----------+-----------+------------------+------------+----------+------------+  
| 1          | Doe      | John      | jdoe@email.com   | Personal   | 555-2222 | Mobile     |
+-------------------------------------------------------------------+----------+------------+

Как я могу отобразить информацию в php без избыточных данных и можно ли оптимизировать мой запрос?

Ответы [ 4 ]

0 голосов
/ 28 июня 2010

Поскольку типы неизвестны, вы можете использовать некоторую группировку на стороне PHP, расширив другой ответ на аналогичный вопрос по PHP: Группировка записей из цикла 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']
    }
}
0 голосов
/ 28 июня 2010

Если ваши типы электронной почты и телефона совпадают, вы можете сгладить их в одну строку, возвращая различные типы в виде проецируемых столбцов, например, для типов электронной почты:

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
0 голосов
/ 28 июня 2010

Если у вас есть непоследовательное / неизвестное количество электронных писем или телефонных номеров и т. Д., То вам может быть лучше получить данные с помощью нескольких операторов выбора. Все зависит от того, как вы хотите использовать данные на стороне веб-сервера. Скорее всего, вам не нужно это в этом формате таблицы.

Если вас беспокоит производительность выполнения нескольких запросов, помните, что иногда вы можете поместить несколько операторов в один запрос и получить несколько наборов результатов. Я не знаю, можно ли это сделать с помощью PHP, но я бы предположил, что это так.

0 голосов
/ 28 июня 2010

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

Обратите внимание, что я никогда не использовал GROUP_CONCAT вокруг обычного CONCAT, но я не вижу причин, почему он не будет работать.

...