Reputation: 25
I am trying to fetch multiple values from a table, with a GROUP BY targeting only one of the columns. To simplify things, I'll use a mockup guestbook table as an example:
postNumber | user | text | date | portal
-----------------------------------------------
1 | Michael | "nice blog" | 10/12| fitness
2 | Ronald | "hello!" | 12/12| lounge
1 | Michael | "beautiful" | 05/11| pictures
2 | Sandra | "great pic" | 10/12| pictures
Let's assume the frontpage of the guestbook must print the latest guest posts, but only one per portal (fitness, lounge and pictures). The desired outcome would be:
The excluded post wold be Michael/"beautiful"/pictures, since it is not the latest one of that portal.
The following query is invalid with more modern mySQL servers, throwing the error described below:
SELECT max(postNumber), user, text, date, portal FROM guestbook GROUP BY portal;
GROUP BY clause and contains nonaggregated column 'database.table.columnName' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
However, this more limited query below works in achievement the desired outcome, but it cannot fecth the remaining needed columns (user,text,date), which is what I'm having trouble with precisely:
SELECT max(postNumber), portal FROM guestbook GROUP BY portal;
It should be noted that the first query can be fixed by adding user,text and date to GROUP BY, but doing a composite grouping like that would no longer retrieve only one entry per portal.
If anyone has a solution to this problem, please elaborate as I have been unable to find a way by myself or through online research.
Edit: I have attempted the following query, with no results as the RIGHT JOIN is giving me the values from the left table (only portal and post number), unsure as of why:
'SELECT t1.portal, max(t1.postNumber) from guestbook t1 RIGHT OUTER JOIN (SELECT * from guestbook) t2 on t1.postNumber = t2.postNumber GROUP BY portal LIMIT ?';
Upvotes: 1
Views: 325
Reputation: 138
Please try the following query
SELECT *
FROM (SELECT postNumber,
user,
text,
date,
@current_portal := portal,
@portal_rank := IF(@current_portal = portal and @portal_rank = portal, @portal_rank + 1, 1) AS portal_rank,
FROM guestbook
ORDER BY portal, date DESC) ranked
WHERE portal_rank = 1)
Rank the portal, using the portal_rank variable, and order by portal and date desc. In this way you are selecting only the latest record for every portal
I think this query is easier to understand and there is no need to do multiple joins on a single table when you can use a variable instead.
Additionally switching the condition portal_rank = 1 with portal_rank lets say <= 3 you can get 3 latest records per portal with minimum query changes.
Hope this helps.
Upvotes: 1
Reputation: 48179
You are on the right track... Do a pre-query as a basis of what records you want, then re-join to the same original table on the qualifying date condition..
select
PreQuery.Portal,
PreQuery.LatestPostNumber,
T2.User,
T2.Text,
T2.Date
from
( select
t1.Portal,
max( t1.PostNumber ) as LatestPostNumber
from
GuestBook T1
group by
t1.Portal ) PreQuery
JOIN GuestBook T2
on PreQuery.Portal = T2.Portal
AND PreQuery.PostNumber = T2.PostNumber
Upvotes: 1