【问题标题】:How to emulate full outer join in this query?如何在此查询中模拟完全外部联接?
【发布时间】:2011-09-01 02:40:18
【问题描述】:

显然 mySQL 不支持完全外连接,但它确实是我需要的。我看过一堆关于用联合来模拟它的博客文章和文章,但这会删除重复项。有人可以帮我从这里出去吗?

这是包含完整外连接的查询(这里只完成了许多连接中的一个);我如何将其翻译成 mySQL 可以理解的内容?

SELECT DISTINCT n.title, nr.teaser, n.nid, DATE_FORMAT(FROM_UNIXTIME(n.created), '%M %e, %Y') AS date, f.filepath AS image,tn_img.tid as image_tid

FROM node n 

JOIN node_revisions nr ON n.nid = nr.nid 
LEFT JOIN content_field_related_images cfri ON (n.nid = cfri.nid AND cfri.delta = 0) 
LEFT JOIN content_field_att_file cfaf ON cfri.field_related_images_nid = cfaf.nid 
LEFT JOIN files f ON cfaf.field_att_file_fid = f.fid   
JOIN term_node tn2 ON n.nid = tn2.nid 
FULL OUTER JOIN term_node tn_img ON cfri.field_related_images_nid = tn_img.nid

WHERE n.status = 1 
AND n.type = 'article'   
AND nr.body LIKE '%kimberly-clark%' 
AND tn2.tid = 143

ORDER BY n.created DESC LIMIT 3

【问题讨论】:

标签: mysql full-outer-join


【解决方案1】:

你基本上做一个左和右连接的联合。

您实际上有一个有趣的问题,您还想将行数限制为 3。要解决这个问题,您需要

  • 将“左”和“右”选择限制为 3
  • 然后在内联视图中使用 UNION 的结果
  • 然后再次将联合限制为 3

更新遗憾的是,除非我弄错了,否则您不能直接在 UNION 中执行此操作,因此您需要在 UNION 之前添加另一层内联视图

UNION 中的 LIMITS 将提供一些性能优势,然后之后的限制将为您提供正确的结果。

SELECT title, 
   teaser, 
   nid, 
   DATE, 
   image, 
   image_tid 
FROM   (SELECT title, 
               teaser, 
               nid, 
               DATE, 
               image, 
               image_tid,
               created 
        FROM   (SELECT DISTINCT n.title, 
                                nr.teaser, 
                                n.nid, 
                                Date_format(From_unixtime(n.created), 
                                '%M %e, %Y') AS 
                                DATE, 
                                f.filepath 
                                AS 
                                image, 
                                tn_img.tid 
                                AS 
                                image_tid 
                                       , 
                                n.created 
                FROM   node n 
                       JOIN node_revisions nr 
                         ON n.nid = nr.nid 
                       LEFT JOIN content_field_related_images cfri 
                         ON ( n.nid = cfri.nid 
                              AND cfri.delta = 0 ) 
                       LEFT JOIN content_field_att_file cfaf 
                         ON cfri.field_related_images_nid = cfaf.nid 
                       LEFT JOIN files f 
                         ON cfaf.field_att_file_fid = f.fid 
                       JOIN term_node tn2 
                         ON n.nid = tn2.nid 
                       LEFT OUTER JOIN term_node tn_img 
                         ON cfri.field_related_images_nid = tn_img.nid 
                WHERE  n.status = 1 
                       AND n.TYPE = 'article' 
                       AND nr.body LIKE '%kimberly-clark%' 
                       AND tn2.tid = 143 
                ORDER  BY n.created DESC 
                LIMIT  3) tleft 
        UNION 
        SELECT title, 
               teaser, 
               nid, 
               DATE, 
               image, 
               image_tid,
               created  
        FROM   (SELECT DISTINCT n.title, 
                                nr.teaser, 
                                n.nid, 
                                Date_format(From_unixtime(n.created), 
                                '%M %e, %Y') AS 
                                DATE, 
                                f.filepath 
                                AS 
                                image, 
                                tn_img.tid 
                                AS 
                                image_tid 
                                       , 
                                n.created 
                FROM   node n 
                       JOIN node_revisions nr 
                         ON n.nid = nr.nid 
                       LEFT JOIN content_field_related_images cfri 
                         ON ( n.nid = cfri.nid 
                              AND cfri.delta = 0 ) 
                       LEFT JOIN content_field_att_file cfaf 
                         ON cfri.field_related_images_nid = cfaf.nid 
                       LEFT JOIN files f 
                         ON cfaf.field_att_file_fid = f.fid 
                       JOIN term_node tn2 
                         ON n.nid = tn2.nid 
                       RIGHT OUTER JOIN term_node tn_img 
                         ON cfri.field_related_images_nid = tn_img.nid 
                WHERE  n.status = 1 
                       AND n.TYPE = 'article' 
                       AND nr.body LIKE '%kimberly-clark%' 
                       AND tn2.tid = 143 
                ORDER  BY n.created DESC 
                LIMIT  3) tright) t 
ORDER  BY created DESC 
LIMIT  3 

更新 这里使用 spencer7593 和 ypercube 建议是使用两个 UNION ALL 语句且没有内联视图的替代方法。

SELECT DISTINCT n.created, 
                n.title, 
                nr.teaser, 
                n.nid, 
                Date_format(From_unixtime(n.created), '%M %e, %Y') AS DATE, 
                f.filepath                                         AS image, 
                tn_img.tid                                         AS image_tid 
FROM   node n 
       JOIN node_revisions nr 
         ON n.nid = nr.nid 
       LEFT JOIN content_field_related_images cfri 
         ON ( n.nid = cfri.nid 
              AND cfri.delta = 0 ) 
       LEFT JOIN content_field_att_file cfaf 
         ON cfri.field_related_images_nid = cfaf.nid 
       LEFT JOIN files f 
         ON cfaf.field_att_file_fid = f.fid 
       JOIN term_node tn2 
         ON n.nid = tn2.nid 
       LEFT OUTER JOIN term_node tn_img 
         ON cfri.field_related_images_nid = tn_img.nid 
WHERE  n.status = 1 
       AND n.TYPE = 'article' 
       AND nr.body LIKE '%kimberly-clark%' 
       AND tn2.tid = 143 

UNION ALL 
SELECT DISTINCT n.created, 
                n.title, 
                nr.teaser, 
                n.nid, 
                Date_format(From_unixtime(n.created), '%M %e, %Y') AS DATE, 
                f.filepath                                         AS image, 
                tn_img.tid                                         AS image_tid 
FROM   node n 
       JOIN node_revisions nr 
         ON n.nid = nr.nid 
       LEFT JOIN content_field_related_images cfri 
         ON ( n.nid = cfri.nid 
              AND cfri.delta = 0 ) 
       LEFT JOIN content_field_att_file cfaf 
         ON cfri.field_related_images_nid = cfaf.nid 
       LEFT JOIN files f 
         ON cfaf.field_att_file_fid = f.fid 
       JOIN term_node tn2 
         ON n.nid = tn2.nid 
       RIGHT JOIN term_node tn_img 
         ON cfri.field_related_images_nid = tn_img.nid 
WHERE  n.status = 1 
       AND n.TYPE = 'article' 
       AND nr.body LIKE '%kimberly-clark%' 
       AND tn2.tid = 143 
       AND cfri.field_related_images_nid IS NULL 
ORDER  BY 1 DESC 
LIMIT 
3 

【讨论】:

  • 哇,好吓人!我会试一试,看看它会返回什么。谢谢。
  • 好的,刚刚试了一下,得到了这个:#1054 - 'order Clause' 中的未知列'created'。我尝试将最终 order by 子句更改为 n.created,但它给了我同样的错误,所以我不确定它指的是什么。另外,你能解释一下 cfri.delta = 0 指的是什么吗?
  • @Emmy -- 在UNIONUNION ALL 查询中,ORDER BY 子句按位置而不是按名称引用列(例如,获取按第一个列排序的结果集结果集,ORDER BY 1)。还可以考虑使用UNION ALL 而不是UNION 以避免消除重复行。
  • @Conrad - 实际上,可以在一个查询中使用 UNION ALL 来模拟 FULL OUTER JOIN(您希望这样做以保留重复项),使用三个查询:一个内部连接、一个左连接和右连接。例如SELECT . FROM l INNER JOIN r UNION ALL SELECT . FROM l LEFT JOIN r WHERE r.id IS NULL UNION ALL SELECT . FROM l RIGHT JOIN r WHERE l.id IS NULL
  • 借口在没有阅读整个查询的情况下闯入,但不能使用 UNION ALL 的 2 个查询来完成 FULL OUTER JOIN(SELECT . FROM l LEFT JOIN r) UNION ALL (SELECT . FROM l RIGHT JOIN r WHERE l.id IS NULL) ?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 2011-01-06
  • 2013-05-09
  • 2017-08-04
相关资源
最近更新 更多