【问题标题】:Full Outer Join with multiple tables in mysqlmysql中多个表的完全外连接
【发布时间】:2014-08-08 23:15:15
【问题描述】:

我被困在 1 个查询中。我想在 1 个网格/行中显示客户的所有产品以及系统收到的所有短信。我可以做到这一点,但问题是只显示客户产品我需要 3 4 个其他表来加入并显示所有数据,如产品型号、客户名称等。其他的东西来自其他表。所以我需要 2 个表来做外连接,并显示来自 4 5 个表的数据。我试过了,但失败了。

Select      tcp.*
            , concat(tc.firstname,' ',tc.lastname)  as cust_id
            , tc.mobile
            , tb.brand_name                         as brand
            , tgt.gadget_type                       as gadget_type
            , tm.model_name                         as model
            , ttt.ticket_type                       as ticket_type
            , trs.registration_source               as registration_source 
From        tbl_cust_products                       tcp  
Left Join   `tbl_received_sms`                      trsm    on  tcp.id = trsm.cust_prod_id 
Left Join   tbl_customer                            tc      on  tcp.cust_id=tc.id 
Left Join   tbl_brand                               tb      on  tcp.brand = tb.id 
Left Join   tbl_gadget_type                         tgt     on  tcp.gadget_type=tgt.id 
Left Join   tbl_model                               tm      on  tcp.model = tm.id 
Left Join   tbl_ticket_type                         ttt     on  tcp.ticket_type=ttt.id 
Left Join   tbl_registration_source                 trs     on  trs.id=tcp.registration_source 
Where       tcp.del_date is NULL 
Union 
Select      tcp.*
            , concat(tc.firstname,' ',tc.lastname)  as cust_id
            , tc.mobile
            , tb.brand_name                         as brand
            , tgt.gadget_type                       as gadget_type
            , tm.model_name                         as model
            , ttt.ticket_type                       as ticket_type
            , trs.registration_source               as registration_source 
From        tbl_cust_products                       tcp  
Right Join  `tbl_received_sms`                      trsm    on  tcp.id=trsm.cust_prod_id 
Left Join   tbl_customer                            tc      on  tcp.cust_id=tc.id 
Left Join   tbl_brand                               tb      on  tcp.brand=tb.id 
Left Join   tbl_gadget_type                         tgt     on  tcp.gadget_type=tgt.id 
Left Join   tbl_model                               tm      on  tcp.model = tm.id 
Left Join   tbl_ticket_type                         ttt     on  tcp.ticket_type=ttt.id 
Left Join   tbl_registration_source                 trs     on  trs.id=tcp.registration_source 
Where       tcp.del_date is NULL

在上面我只想在tbl_cust_productstbl_received_sms 表上进行外连接。我在这里尝试了 outer join 的联合。当我搜索并发现 MySql do not support direct outer join 和其他大型数据库处理程序一样。

如果我在使用 union 或任何逻辑时犯了任何错误,请帮助我实现这一点..

已编辑 问题: tbl_received_sms 有 7,734 条记录,tbl_cust_products 有 3 条记录。所以我需要总共 7737 条记录。如果我只使用UNION,我会得到3条记录,如果我使用UNION ALL,我会得到7737条记录,但所有记录的所有字段都是NULL

【问题讨论】:

  • 您只想要tbl_cust_productstbl_received_sms 之间的外连接?每个查询有 7 个外部联接。 Left JoinRight JoinFull Join 都是 outer joins 的类型。 outer 关键字只是可选的。
  • 您是否尝试过终止联合并将第一个联接更改为 Full Join
  • 尝试使用UNION ALL而不是UNION
  • 如果我使用 UNION ALL 所有数据都为 NULL
  • 您的语法看起来不错。您遇到的实际问题是什么?查询是否失败,带回错误的数据或太慢。顺便说一句,查询的第二部分带回 tbl_received_sms 的记录,并将其与 tml_cust_products 匹配。如果没有匹配的记录,那么您在 SELECT 中返回的每个字段都将为 NULL。因此,UNION 将消除它们,除了一个(因为它们将被视为重复项)。任何在 tbl_cust_products 上匹配的内容都会被第一个选择带回来。 UNION ALL 只会带回大量 NULL 行

标签: php mysql sql join full-outer-join


【解决方案1】:

问题是您的查询从表 tcp (tbl_cust_products)、tc (tbl_customer)、tb (tbl_brand)、tgt (tbl_gadget_type)、tm (tbl_model)、ttt (tbl_ticket_type) 和 trs (tbl_registration_source) 返回列。

所有这些列都依赖于 tcp (tbl_cust_products) 表中存在的记录,因为它们要么来自此表,要么来自与此表上的记录进行了 LEFT OUTER JOIN 的表。

第一个查询将返回在 tcp (tbl_cust_products) 上有匹配记录的任何行。第二个查询还将返回在 trsm (tbl_received_sms) 上有匹配记录的任何这些。但是,两者都返回的任何内容都会被 UNION 消除一次。

进一步的问题是,从第二个查询返回的任何行在 tcp (tbl_cust_products) 上没有匹配记录的情况下,在部分查询返回的所有字段中都将具有 NULL(因为所有字段都取决于匹配在 tcp (tbl_cust_products) 上。然后,UNION 将消除除其中一行之外的所有行,因为它消除了重复,并且所有行都完全相同(即所有 NULL)。

如果您想从中获取输出,则将 trsm (tbl_received_sms) 中的一列添加到返回的列中。可能 trsm.cust_prod_id 会是一个不错的尝试。

编辑更多细节以解释工会。

以您的查询的高度简化版本为例:-

SELECT tcp.id,
    tc.name
FROM        tbl_cust_products                       tcp  
LEFT JOIN   tbl_received_sms                      trsm    ON  tcp.id = trsm.cust_prod_id 
LEFT JOIN   tbl_customer                            tc      ON  tcp.cust_id=tc.id 
UNION
SELECT tcp.id,
    CONCAT(tc.firstname,' ',tc.lastname)  as cust_id
FROM        tbl_cust_products                       tcp  
RIGHT JOIN   tbl_received_sms                      trsm    ON  tcp.id = trsm.cust_prod_id 
LEFT JOIN   tbl_customer                            tc      ON  tcp.cust_id=tc.id 

假设表格包含以下内容

tbl_cust_products
id  name    cust_id
1   a   5
2   b   6

tbl_received_sms
id  cust_prod_id    data
3   2       c
4   3       d
5   4       e

tbl_customer
id  name
5   fred
6   burt

第一个查询将返回来自 tbl_cust_products 的两条记录,其中一条与 tbl_received_sms 匹配:-

id  name
1   fred
2   burt

第二个查询将从 tbl_received_sms 中找到 3 条记录,其中一条与 tbl_cust_products 匹配。不匹配的记录在两个返回的字段中都为 NULL(因为 tbl_cust_products 上没有匹配的记录,所以该字段的值为 null,与 tbl_customer 中的字段值相同,这将匹配来自 tbl_cust_products 的不存在记录)。匹配的记录将被填充:-

id      name
NULL    NULL
NULL    NULL
2       burt

UNION 会将这两个地段合并在一起,

id      name
1       fred
2       burt
NULL    NULL
NULL    NULL
2       burt

但消除了重复,因此:-

id      name
1       fred
2       burt
NULL    NULL

【讨论】:

  • trsm.cust_prod_id 也将像 trsm.cust_id 一样为空白,所以我认为它不会有任何变化。空值不是问题,但我也想查看所有其他可用记录,但我不是得到它..
  • 正如解释的那样,您无法从那些“其他可用记录”中带来任何东西。因此,对于第二个查询中的任何可用记录,所有字段都为空。 UNION ALL 将带回所有这些记录,但由于列都是 NULL,它们将只是空记录(并且在两个表上匹配的一些记录将被复制)。
猜你喜欢
  • 2015-05-02
  • 2013-03-11
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多