mysql查询两个表

时间:2012-01-24 15:54:22

标签: mysql sql

我需要像这样查询两个表......

表一。
客户

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

所以它返回所有公司与山姆和所有联系人.... 同样如果我会搜索“微软”它应该返回没有雅虎

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 个答案:

答案 0 :(得分:4)

这是一个棘手的问题,我几乎想说“不要试图这样做是一个查询”。

我从编程角度处理这样的SQL查询,因为我觉得结果往往不那么“神奇”。 (我在太多查询中看到的一个属性 - 现在看来SQL查询是在键盘上使用猴子编写的......)

  1. 找出我们要列出的公司ID。这是这两件事的结合:
    1. 任何“人”结果与姓名或号码相匹配
    2. 任何“公司”结果与姓名或号码相匹配
  2. 列出该公司的人数以及人数。
  3. 让我们先做#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
        )
    ;
    

    并祈祷数据库可以找出在合理的时间内执行此操作的查询计划。当然你不想几次往返数据库?

    请注意方法:我们确定了我们想要的内容(“客户/联系人的姓名/电话与某些公司匹配”),然后找出丢失的部分(“公司ID?”)。这是因为一旦你匹配公司中的某个人(例如,山姆),你就需要来自该公司的所有人,以及该公司或具有该公司ID的所有内容。知道了,我们得到了外部查询(#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!