【问题标题】:MS Access Outer Join Multiple Fields to Single RecordMS Access 外部连接多个字段到单个记录
【发布时间】:2011-08-03 22:57:28
【问题描述】:

我需要做与此处所示完全相同的事情:INNER or LEFT Joining Multiple Table Records Into A Single Row,但让它在 MS Access Query 中工作。

下面是场景:


电话桌

+----------------+-------------+
| Field          | Type        |
+----------------+-------------+
| f_id           | int(15)     |
| f_client_id    | int(11)     |
| f_phone_type   | varchar(50) |
| f_phone_number | varchar(13) |
+----------------+-------------+

客户表

+-----------------------------+--------------+------+-----+
| Field                       | Type         | Null | Key |
+-----------------------------+--------------+------+-----+
| f_id                        | int(15)      | NO   | PRI |
| f_first_name                | varchar(13)  | YES  | MUL |
| f_mi                        | char(1)      | YES  |     |
| f_last_name                 | varchar(20)  | NO   | MUL |
+-----------------------------+--------------+------+-----+

使用标准的 LEFT 或 INNER 连接,我会得到这样的结果:

+------------+------------+--------------+
| name       | Phone Type | Phone Number |
+------------+------------+--------------+
| John Smith | Home       | 712-555-6987 |
| John Smith | Work       | 712-555-1236 |
+------------+------------+--------------+

我需要一个查询,以提供属于给定客户的工作和家庭电话号码:

+------------+----------------+--------------+
| Name       | Work Number    | Home Number  |
+------------+----------------+--------------+
| John Smith | 712-555-1236   | 712-555-6987 |
+------------+----------------+--------------+

SQL 中的解决方案是

SELECT CONCAT(c.f_first_name, ' ', c.f_last_name) as Client_Name, 
       wp.f_phone_number as Work_Number,
       hp.f_phone_number as Home_Number

  FROM clients c
       LEFT OUTER JOIN phone hp
       ON hp.f_client_id = c.f_id
    AND
       hp.phone_type = 'home'
       LEFT OUTER JOIN phone wp
       ON wp.f_client_id = c.f_id
    AND
       wp.phone_type = 'work'

但这并不能转化为 MS Access,加入失败。通过 Access 完成相同任务的最佳方式是什么?

【问题讨论】:

    标签: database ms-access


    【解决方案1】:

    还有两个问题你还没有发现。

    1. Access 或其数据库引擎中没有 CONCAT() 函数
    2. 您的查询尝试使用 phone_type,但实际的字段名称是 f_phone_type

    当连接两个以上的表时,Access 的数据库引擎需要括号。使用查询设计器设置连接是最简单的方法。查询设计器还将用 LEFT JOIN 替换 LEFT OUTER JOIN;在 Access 2003 中,任何一种方式都适用于我。

    这个很容易在查询设计器中构建,但只为同时拥有家庭和工作号码的客户返回行。我以它为起点,然后调整了类似于您原来的 ON 子句。

    SELECT
        c.f_first_name & " " & c.f_last_name AS [Name],
        wp.f_phone_number AS [Work Number],
        hp.f_phone_number AS [Home Number]
    FROM
        (Clients AS c
        LEFT JOIN Phones AS hp
        ON c.f_id = hp.f_client_id)
        LEFT JOIN Phones AS wp
        ON c.f_id = wp.f_client_id
    WHERE
        hp.f_phone_type='Home'
        AND wp.f_phone_type='Work';
    

    将这些 WHERE 条件移动到 ON 表达式中,就像在您的 SQL Server 示例中一样,将返回所有客户端,无论您是否有任何电话号码为他们存档。然而,这种方法需要在 ON 表达式周围加上括号。并且这些 JOINS 无法在查询设计器中显示。

    SELECT
        c.f_first_name & " " & c.f_last_name AS [Name],
        wp.f_phone_number AS [Work Number],
        hp.f_phone_number AS [Home Number]
    FROM
        (Clients AS c
        LEFT JOIN Phones AS hp
        ON (c.f_id = hp.f_client_id AND hp.f_phone_type='Home'))
        LEFT JOIN Phones AS wp
        ON (c.f_id = wp.f_client_id AND wp.f_phone_type='Work');
    

    更新:就我自己而言,我更喜欢用子查询来做这件事。

    SELECT
        c.f_first_name & " " & c.f_last_name AS [Name],
        wp.f_phone_number AS [Work Number],
        hp.f_phone_number AS [Home Number]
    FROM
        (Clients AS c
        LEFT JOIN [
            SELECT f_client_id, f_phone_number
            FROM Phones
            WHERE f_phone_type='Home'
        ]. AS hp
        ON c.f_id = hp.f_client_id)
        LEFT JOIN [
            SELECT f_client_id, f_phone_number
            FROM Phones
            WHERE f_phone_type='Work'
        ]. AS wp
        ON c.f_id = wp.f_client_id;
    

    【讨论】:

    • 太棒了,正是我需要的!我发现 WHERE 子句方法只返回包含两个电话号码的行,我什至需要显示空白号码,所以我使用了第一种方法。我还切换到 LEFT OUTER JOIN 以确保返回所有记录,并且它似乎在 Access 2010 中工作正常。再次感谢!
    • 对,我在 WHERE 子句上犯了一个错误,这违背了 LEFT JOIN 的目的。另外,我对 LEFT OUTER JOIN 与 LEFT JOIN 感到困惑。引擎确实接受 LEFT OUTER JOIN,查询设计器将其转换为 LEFT JOIN。我编辑了解决这些问题的答案,并添加了子查询方法。
    • 在 Jet/ACE 的 SQL 方言中,LEFT OUTER JOIN 是 LEFT JOIN 的同义词。我很确定它也适用于所有其他 SQL 方言。您可以输入额外的单词,但如果您保存查询,Jet/ACE 会将其删除并留下 LEFT JOIN,因此根本没有任何实用程序可以输入。
    【解决方案2】:

    也可以使用子查询,如:

    SELECT (firstname & " " & lastname ) AS fullname,
      (SELECT f_PhoneNumber FROM tblPhones 
       WHERE  f_clientID = clients.id AND f_PhoneType = "Home")
       AS HomeNumber,
      (SELECT f_PhoneNumber FROM tblPhones 
       WHERE  f_clientID = clients.id AND f_PhoneType = "Work")
       AS WorkNumber
    FROM clients
    

    【讨论】:

    • 谢谢阿尔伯特,我很感激这个小费!我使用了另一种发布的方法。我不确定这两种方法是否存在性能差异,但有些东西让我回避选择中的选择......可能完全没有根据!我确信这两个答案都给出了预期的结果。
    • 我可能也会加入。但是,上面的语法适用于 sql server 并且可能适用于 MySql。通常编写这样的子查询更容易编写,并且可能只是一个 FYI,即 JET sql 中提供了子查询,它们通常可以轻松解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    相关资源
    最近更新 更多