MySQL запросить две таблицы - PullRequest
       4

MySQL запросить две таблицы

4 голосов
/ 24 января 2012

Мне нужно запросить две таблицы, подобные этой ...

таблица одна
клиенты

id     companyname     phone  
1   |  microsoft    |  888-888-8888
2   |  yahoo        |  588-555-8874
3   |  google       |  225-558-4421

и т. Д. *

таблица две
контакты

id     companyid    name    phone
1   |      1     |  sam   |  558-998-5541
2   |      1     |  john  |  558-998-1154
3   |      3     |  larry |  111-145-7885
4   |      3     |  dave  |  558-998-5254
5   |      2     |  sam   |  558-997-5421

Мне нужно запросить обе таблицы.

Так что, если я ищу sam , он должен вернуть список компаний с контактами

microsoft  888-888-8888
      sam  558-998-5541
     john  558-998-1154
yahoo      588-555-8874
      sam  558-997-5421

, поэтому он возвращает всю компанию с sam и все контакты с ним.... то же самое, если я буду искать "Microsoft", он должен вернуться без Yahoo

microsoft 888-888-8888
     sam  558-998-5541
     john 558-998-1154

, и если я ищу "558-998-1154", он должен вернуться, как это ...

 microsoft 888-888-8888
      sam  558-998-5541
      john 558-998-1154

Надеюсь, это понятно ....

Вот мой текущий запрос:

SELECT * FROM 
customers, customer_contacts 
WHERE (customers.code LIKE '%#URL.qm1#%' 
       or customers.COMPANY LIKE '%#URL.qm1#%' 
       or customers.phone LIKE '%#URL.qm1#%' 
       or customers.contact LIKE '%#URL.qm1#%' 
       or customers.name LIKE '%#URL.qm1#%' 
       or customers.address1 LIKE '%#URL.qm1#%') 
AND (customers.id = customer_contacts.cid 
       and customer_contacts.deleted = 0)

это возвращает только тех, кто имеет контакт ...

Мне нужно было бы вернуть и те, у кого нет контактов.

1 Ответ

4 голосов
/ 25 января 2012

Это сложная проблема, о которой я почти хочу сказать «не пытайтесь сделать это одним запросом».

Я подхожу к SQL-запросам, как это, с точки зрения программирования, так как я чувствую, чторезультаты имеют тенденцию быть менее "волшебными".(Свойство, которое я вижу в слишком многих запросах - кажется, что запросы SQL в наши дни пишутся с использованием обезьян на клавиатурах…)

  1. Выясните, какие идентификаторы компании мы хотим перечислить.Это объединение этих двух вещей:
    1. Любые результаты "людей" совпадают по имени или номеру
    2. Любые результаты "компании" совпадают по имени или номеру
  2. Укажите номер этой компании, а также людей.

Давайте сначала сделаем # 2:

    SELECT
        companyname AS name,
        phone
    FROM
        customers
    WHERE id IN (company_ids we want)
UNION
    SELECT
        name, phone
    FROM
        contacts
    WHERE companyid IN (company_ids we want)

Поскольку "company_ids мы хотим" будетбудьте запросом, переставьте это, чтобы свести его к одному вхождению:

SELECT
    name, phone
FROM
    (
        SELECT
            id AS companyid,
            companyname AS name,
            phone
        FROM
            customers
    UNION
        SELECT companyid, name, phone FROM contacts
    ) AS entities
WHERE
    companyid IN (company_ids we want)

Теперь, чтобы заполнить интересную часть, нам нужно ответить # 1:

Часть # 1.1:

SELECT companyid FROM contacts WHERE name = $search OR number = $search;

Часть # 1.2:

SELECT id AS companyid FROM customers WHERE companyname = $search OR number = $search;

(Обратите внимание, что $search - это наши входные параметризованные запросы сильно отличаются от одного поставщика SQL к другому, поэтому замените этот синтаксиспо мере необходимости.)

Поместите UNION из этих двух в IN, и мы закончили:

SELECT
    name, phone
FROM
    (
        SELECT
            id AS companyid,
            companyname AS name,
            phone
        FROM
            customers
    UNION
        SELECT companyid, name, phone FROM contacts
    ) AS entities
WHERE
    companyid IN (
            SELECT companyid FROM contacts WHERE name = $search OR phone = $search
        UNION
            SELECT id AS companyid FROM customers WHERE companyname = $search OR phone = $search
    )
;

И молитесь, чтобы база данных могла выяснить план запроса, которыйвыполняет это в разумные сроки.Уверены, что не хотите заходить в БД несколько раз?

Обратите внимание на методологию: мы определили, что нам нужно («имена / телефоны для клиентов / контакты, соответствующие определенным компаниям»), а затем выяснилинедостающий кусок («какие компании идентификаторы?»).Это происходит из-за того, что после того, как вы сопоставите конкретного человека в компании (скажем, Сэма), вы захотите всех из этой компании плюс компания или все с этим идентификатором компании.Зная это, мы получаем наш внешний запрос (# 2), а затем нам просто нужно выяснить, как определить, какие компании нас интересуют.

Обратите внимание, что это не будет (и запросы SQL, безORDER BY не) возвращать запросы в вашем довольно причудливом порядке.Однако вы можете добавить вспомогательный столбец к внутреннему запросу и выполнить это:

SELECT
    name, phone
FROM
    (
        SELECT
            0 AS is_person,
            id AS companyid,
            companyname AS name,
            phone
        FROM
            customers
    UNION
        SELECT 1 AS is_person, companyid, name, phone FROM contacts
    ) AS entities
WHERE
    companyid IN (
            SELECT companyid FROM contacts WHERE name = $search OR phone = $search
        UNION
            SELECT id AS companyid FROM customers WHERE companyname = $search OR phone = $search
    )
ORDER BY
    companyid, is_person, name
;

Вы также можете использовать столбец is_person (если вы добавите его в SELECT), если вам нужноСегментируйте результаты так, чтобы получались результаты этого запроса.

(И если вы в конечном итоге будете использовать запросы такой длины, пожалуйста, ради любви к Богу, -- comment them!)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...