简体   繁体   中英

mysql - convert this INNER JOIN to UNION

I can not get this to work. I want to convert this query to UNION to remove OR in notifies 's INNER JOIN.

SELECT posts.status, posts.reports, posts.private_id,
    enter code hereposts.parent_id, posts.post_id,
    posts.reply_counts, posts.sender, posts.content, 
    posts.image, posts.thumb, posts.date,members.username, 
    members.avatar,members.avatar_path,members.level, members.state 
FROM posts
INNER JOIN members ON posts.sender = members.member_id 
INNER JOIN notifies ON (
    posts.post_id=notifies.post_id OR posts.parent_id=notifies.post_id
) 
WHERE  (posts.date>notifies.last_date AND posts.sender<>1) 
    AND notifies.member_id=1 
    AND posts.private_id<>0 
    AND posts.status=1 
    AND posts.reports<3  
ORDER BY posts.last_update DESC, posts.date DESC LIMIT 0,25;

my try that not working:

(SELECT posts.status, posts.reports, posts.private_id , posts.parent_id, 
    posts.post_id, posts.reply_counts, posts.sender, posts.content, 
    posts.image, posts.thumb, posts.date, members.username, members.avatar,
    members.avatar_path,members.level, members.state 
FROM posts 
INNER JOIN members ON posts.sender = members.member_id 
INNER JOIN notifies ON posts.parent_id=notifies.post_id) 

UNION

(SELECT posts.status, posts.reports, posts.private_id , posts.parent_id,  
    posts.post_id, posts.reply_counts, posts.sender, posts.content, 
    posts.image, posts.thumb, posts.date, members.username, members.avatar,
    members.avatar_path,members.level, members.state 
FROM posts 
INNER JOIN members ON posts.sender = members.member_id 
INNER JOIN notifies ON posts.post_id=notifies.post_id) 
WHERE  (posts.date>notifies.last_date AND posts.sender<>1) 
    AND notifies.member_id=1 
    AND posts.private_id<>0
    AND posts.status=1 
    AND posts.reports<3  
ORDER BY posts.last_update DESC, posts.date DESC LIMIT 0,25;

It seems that you only added the where clause to the last section of the UNION, and not to both.

So you went from

SELECT *
FROM  A INNER JOIN
B ON (a.ID = b.ID OR a.ID = b.ID2)
WHERE tada

to

SELECT *
FROM  A INNER JOIN
B ON (a.ID = b.ID)
UNION
SELECT *
FROM  A INNER JOIN
B ON (a.ID = b.ID2)
WHERE tada

So you need to do something like

SELECT *
FROM  A INNER JOIN
B ON (a.ID = b.ID)
WHERE tada
UNION
SELECT *
FROM  A INNER JOIN
B ON (a.ID = b.ID2)
WHERE tada

You don't have to change this to a union to make it more efficient. Here is an alternative version (only the from and where clauses shown):

FROM   posts 
       INNER JOIN members 
               ON posts.sender = members.member_id 
       LEFT JOIN notifies n 
               ON ( posts.post_id = n.post_id ) 
       LEFT JOIN notifies np 
               ON ( posts.parent_id = np.post_id ) 
WHERE  ( (posts.date > n.last_date or posts.date > np.last_date)) AND posts.sender <> 1 ) 
       AND (n.member_id = 1 or np.member_id = 1)
       AND posts.private_id <> 0 
       AND posts.status = 1 
       AND posts.reports < 3 

This also removes a duplicate row when both the parent and the post match.

I'm not positive that the date comparison is doing exactly what you want but it should be close.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM