I have been working on this Query to pull data from 3 different tables and use them to determine which rows to pull from another table and in what order. The script I have returns everything just fine, except it has duplicates. I tried using DISTINCT, but by doing so it removes the ORDER BY functionality.
SELECT DISTINCT(p.postId), p.roomId, p.uniqueId, p.title, p.post, p.image, p.createdOn, r.created
FROM posts p
INNER JOIN (
SELECT postId, created FROM (
(
SELECT p.postId, p.createdOn AS created
FROM posts p
WHERE p.deleted = 0
)
UNION
(
SELECT p.postId, c.createdOn AS created
FROM comments c
LEFT JOIN posts p
ON p.postId = c.postId
WHERE p.deleted = 0
AND c.deleted = 0
)
UNION
(
SELECT p.postId, r.createdOn AS created
FROM replies r
LEFT JOIN comments c
ON c.commentId = r.commentId
LEFT JOIN posts p
ON p.postId = c.postId
WHERE p.deleted = 0
AND c.deleted = 0
AND r.deleted = 0
)
) AS everything
) r
ON p.postId = r.postId
WHERE p.deleted = 0
ORDER BY r.created DESC
Should look like:
Code:
3 | 1 | x1b2cxd4e5f6y7h8i9j0k102m3nzo5p6 | This is a test Post 2 | The path of the righteous man is beset on all side... | 1348041600 | 1348041602
2 | 1 | a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 | This is a test Post | The path of the righteous man is beset on all side... | 1348041600 | 1348041601
4 | 1 | pq72cxd4e5f6y7igbej0k102m3nzo5pt | This is a test Post 3 | The path of the righteous man is beset on all side... | 1348041600 | 1348041600
But returns like this:
Code:
2 | 1 | a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 | This is a test Post | The path of the righteous man is beset on all side... | 1348041600 | 1348041600
3 | 1 | x1b2cxd4e5f6y7h8i9j0k102m3nzo5p6 | This is a test Post 2 | The path of the righteous man is beset on all side... | 1348041600 | 1348041600
4 | 1 | pq72cxd4e5f6y7igbej0k102m3nzo5pt | This is a test Post 3 | The path of the righteous man is beset on all side... | 1348041600 | 1348041600
This is all just sample data. But the concept should still be the same. If anybody has any ideas please let me know.
Can you show the result of doing *JUST* the UNION part of that?
And you only show 3 records in the "returns like this". I assume it is actually returning many more?
And you apparently misunderstand how SELECT DISTINCT works.
It applies to *ALL* the fields in your SELECT. If *ANY* fields in the two records are different, then the records are different and the DISTINCT will show them.
Putting parentheses around the field name, as you did with
Code:
SELECT DISTINCT(p.postId), p.roomId, ...
is meaningless. It changes nothing. Remove them and you will get identical results.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
And you only show 3 records in the "returns like this". I assume it is actually returning many more?
Right now there is very limited data in the system for basic testing.
Quote:
Originally Posted by Old Pedant
And you apparently misunderstand how SELECT DISTINCT works.
It applies to *ALL* the fields in your SELECT. If *ANY* fields in the two records are different, then the records are different and the DISTINCT will show them.
Putting parentheses around the field name, as you did with
Code:
SELECT DISTINCT(p.postId), p.roomId, ...
is meaningless. It changes nothing. Remove them and you will get identical results.
The only reason I put parentheses around the field name was because I saw it in a tutorial and was trying it out. But like you said, it returns the same as without the parentheses.
The only reason I put parentheses around the field name was because I saw it in a tutorial and was trying it out. But like you said, it returns the same as without the parentheses.
Well, that's one tutorial you can mark off your places to look at for help, I would say.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
I am trying to output only one instance of any one postId. That is where the DISTINCT comes in. But whenever I add a DISTINCT to the query it completely ignores the ORDER BY function.
I assume you know that doing UNION alone is that same as doing SELECT DISTINCT?
If you want *all* results from a UNION, you must use UNION ALL.
Not clear to me why you have the extra level of SELECT in there.
Try this variation on your query. It might prove instructional/helpful:
Code:
SELECT p.postId, p.roomId, p.uniqueId, p.title, p.post, p.image, p.createdOn, r.created, r.what
FROM posts p
INNER JOIN (
SELECT 'posts' AS what, p.postId, p.createdOn AS created
FROM posts p
WHERE p.deleted = 0
UNION ALL
SELECT 'comments', p.postId, c.createdOn
FROM comments c
LEFT JOIN posts p
ON p.postId = c.postId
WHERE p.deleted = 0
AND c.deleted = 0
UNION ALL
SELECT 'replies', p.postId, r.createdOn
FROM replies r
LEFT JOIN comments c
ON c.commentId = r.commentId
LEFT JOIN posts p
ON p.postId = c.postId
WHERE p.deleted = 0
AND c.deleted = 0
AND r.deleted = 0
) r
ON p.postId = r.postId
WHERE p.deleted = 0
ORDER BY r.created DESC
(So long as I have the "what" field in there, the UNION ALL isn't needed, since you can't get duplicates, but it won't hurt and you may [or may not...depends on what you want] need it when/if you pull out the "what" field.)
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
I am trying to output only one instance of any one postId. That is where the DISTINCT comes in. But whenever I add a DISTINCT to the query it completely ignores the ORDER BY function.
AHH! Okay...ignore my just prior post. I have an idea.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
SELECT p.postId, p.roomId, p.uniqueId, p.title, p.post, p.image, p.createdOn, r.created
FROM posts p
INNER JOIN (
SELECT u.postid, MAX(u.createdOn) AS created
FROM (
SELECT p.postId, p.createdOn
FROM posts p
WHERE p.deleted = 0
UNION
SELECT p.postId, c.createdOn
FROM comments c
LEFT JOIN posts p
ON p.postId = c.postId
WHERE p.deleted = 0
AND c.deleted = 0
UNION
SELECT p.postId, r.createdOn
FROM replies r
LEFT JOIN comments c
ON c.commentId = r.commentId
LEFT JOIN posts p
ON p.postId = c.postId
WHERE p.deleted = 0
AND c.deleted = 0
AND r.deleted = 0
) AS u
GROUP BY u.postid
) AS r
ON p.postId = r.postId
WHERE p.deleted = 0
ORDER BY r.created DESC
I think that's right. Note how using MAX( ) ensures that, indeed, you will get only one "created" date/time for each postid.
If I have the sense of it wrong, you might want to change MAX( ) to MIN( ).
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
3 | 1 | x1b2cxd4e5f6y7h8i9j0k102m3nzo5p6 | This is a test Post 2 | The path of the righteous man is beset on all side... | 1348041600 | 1348041602 | replies
2 | 1 | a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 | This is a test Post | The path of the righteous man is beset on all side... | 1348041600 | 1348041601 | comments
2 | 1 | a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 | This is a test Post | The path of the righteous man is beset on all side... | 1348041600 | 1348041600 | posts
3 | 1 | x1b2cxd4e5f6y7h8i9j0k102m3nzo5p6 | This is a test Post 2 | The path of the righteous man is beset on all side... | 1348041600 | 1348041600 | posts
4 | 1 | pq72cxd4e5f6y7igbej0k102m3nzo5pt | This is a test Post 3 | The path of the righteous man is beset on all side... | 1348041600 | 1348041600 | posts
3 | 1 | x1b2cxd4e5f6y7h8i9j0k102m3nzo5p6 | This is a test Post 2 | The path of the righteous man is beset on all side... | 1348041600 | 1348041600 | comments
3 | 1 | x1b2cxd4e5f6y7h8i9j0k102m3nzo5p6 | This is a test Post 2 | The path of the righteous man is beset on all side... | 1348041600 | 1348041600 | replies
This is an improvement on the code, but it is still returning duplicate postId's. Which is one of the main issues I am having.
(P.S. This is my first time working with UNION, so I had no idea UNION ALL existed.)