问题
So apparently mySQL doesn't support full outer join, but it's really what I need. I've seen a bunch of blog posts and articles about emulating it with unions, but that removes duplicates. Can anyone help me out here?
Here's the query containing the full outer join (only one of a number of joins being done here); how would I translate that into something mySQL understands?
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
回答1:
You basically do a Union of LEFT and RIGHT JOIN.
You actually have interesting wrinkle in that you also want to limit the rows to 3. To solve that you need to
- Limit both The "left" and "right" selects by 3
- Then use the result of the UNION in a inline view
- then Limit the union by 3 again
UPDATE Sadly, unless I'm mistaken you can't do this directly in a UNION so you need to add another layer of inline views prior to the UNION
The LIMITS inside the UNION will offer some performance benefit and then the limit after will give you the correct results.
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
UPDATE Using spencer7593 and ypercube suggestions here's an alternative approach using two UNION ALL statements and no inline views.
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
来源:https://stackoverflow.com/questions/6113806/how-to-emulate-full-outer-join-in-this-query