I have 2 tables
chat_room have two columns : id, slogan
chat have 3 columns : id, chat_room_id,updated_at
this is my code
SELECT chat_room.*
FROM chat_room
ORDER BY (SELECT updated_at FROM chat WHERE chat.chat_room_id = chat_room.id ) DESC;
this is my bug
SELECT chat_room.* FROM chat_room ORDER BY (SELECT updated_at FROM chat WHERE chat.chat_room_id = chat_room.id) DESC LIMIT 0, 1000 Error Code: 1242. Subquery returns more than 1 row 0.00058 sec
The error is telling you that the subquery in the ORDER BY clause sometimes is returning more than one record. This raises the question of which updated_at value you want to use in the case that a given chat room might have more than one value. Assuming you want to sort by the latest updated_at value, you could use:
SELECT cr.*
FROM chat_room cr
INNER JOIN
(
SELECT chat_room_id, MAX(updated_at) AS max_updated_at
FROM chat
GROUP BY chat_room_id
) c
ON c.chat_room_id = cr.id
ORDER BY
c.max_updated_at DESC;
Isn't it better to do a join instead of using a subquery and achieve what you want like this:
SELECT
cr.*
FROM chat_room cr
JOIN chat c on cr.id=c.chat_room_id
order by updated_at desc
Related
I came across this very simple case where I need to select a list of conversations from Conversations table along with latest message from Messages table - which has non-uniqe dateCreated field.
After long research I came up with this query:
SELECT
Conversations.id,
dateCreated,
`name`,
lastMessageId,
lastMessageDate,
lastMessagePayload
FROM Conversations
LEFT JOIN (
SELECT
id AS lastMessageId,
m1.conversationId,
payload AS lastMessagePayload,
m1.dateCreated AS lastMessageDate,
FROM Messages AS m1
INNER JOIN (
SELECT conversationId, MAX(dateCreated) AS mdate FROM Messages GROUP BY conversationId
) AS m2
ON m1.conversationId = m2.conversationId AND m1.dateCreated = m2.mdate
) AS msg2
ON msg2.conversationId = Conversations.id
ORDER BY dateCreated DESC
Query works well but if two latest messages in same conversation have exact same dateCreated field this query would then output two conversations with same id but different lastMessage... row of fields.
I just couldn't find a way to get around this problem as main problem is when you do GROUP BY a field and MAX on another non-uniqe field then you can't get out always only one row out.
Any idea how to get list of unique conversations with latest message (any message of the two if they have the same date)?
Use row_number()!
select c.*, m.* -- or whatever columns you want
from conversations c left join
(select m.*,
row_number() over (partition by m.conversationid order by m.dateCreated desc, m.id desc) as seqnum
from messages m
) m
on m.conversation_id = c.id and
m.seqnum = 1;
MySQL 5.x version...
Use a correlated sub-query to get the latest message id (for a given conversation), using ORDER BY and LIMIT 1
SELECT
Conversations.Conversations.id,
Conversations.dateCreated,
Conversations.`name`,
Messages.id AS lastMessageId,
Messages.payload AS lastMessagePayload,
Messages.dateCreated AS lastMessageDate,
FROM
Conversations
LEFT JOIN
Messages
ON Messages.id = (
SELECT lookup.id
FROM Messages AS lookup
WHERE lookup.conversationId = Conversations.id
ORDER BY lookup.dateCreated DESC
LIMIT 1
)
ORDER BY
Conversations.dateCreated DESC
In the event of two messages having the same date, the message you get is non-deterministic / arbitrary.
You could, if you wanted, therefore change it to get the highest id from the most recent date...
ORDER BY lookup.dateCreated DESC, lookup.id DESC
LIMIT 1
I'm trying to get all results of my table with a GROUP BY on 2 columns and get the last insertions.
"Prices" table :
My Request :
SELECT DISTINCT p.*
FROM prices p
JOIN (
SELECT MAX(created_at) as "last_created"
FROM prices
WHERE station_id = 27210003
GROUP BY station_id, fuel_id) as sub
ON sub.last_created = p.created_at
WHERE p.station_id = 27210003
GROUP BY p.station_id, p.fuel_id
Results are 3 lines but wrong line because not last created in my DB -_-'
Please help me !!! >_<'
Thx
Since you're selecting a specific station_id in the WHERE clause, you don't need to include that in GROUP BY.
The subquery has to return the columns you're grouping on, and then you have to include them in the ON clause.
And you don't need GROUP BY in the outer query, since the JOIN should ensure that there's just one row for each fuel_id (unless there are duplicate created_at for the same fuel_id and station_id).
SELECT DISTINCT p.*
FROM prices p
JOIN (
SELECT fuel_id, MAX(created_at) as "last_created"
FROM prices
WHERE station_id = 27210003
GROUP BY fuel_id) as sub
ON sub.last_created = p.created_at AND sub.fuel_id = p.fuel_id
WHERE p.station_id = 27210003
I want to select the last inserted date and at the same time I want to select the user-name and count how many times the user-profile is visited.
So I am using this query
SELECT v.visitor_date, i.info_name, count(DISTINCT v.visitor_date) AS counted
FROM profile_visitors v
INNER JOIN profile_info i ON i.info_userId = v.visitor_accountId
ORDER BY v.visitor_date DESC
LIMIT 1
The result of the fiddle is wrong and SHOULD be
2015-07-28 11:05:16 - Testname - 5
Anyone knows what is wrong with the query?
http://sqlfiddle.com/#!9/2814c/1
DISTINCT does NOT give you the first or last record of any group, in fact you cannot guarantee which record DISTINCT will display within a group (nor does this matter by the way). So select MAX visitor date.
Try below query
SELECT MAX( v.visitor_date ) , i.info_name, COUNT( DISTINCT v.visitor_date ) AS counted FROM profile_visitors v INNER JOIN profile_info i ON i.info_userId = v.visitor_accountId ORDER BY v.visitor_date DESC LIMIT 1
You can try it:
SELECT v.visitor_date,
i.info_name,
COUNT(*) AS counted
FROM profile_visitors v
INNER JOIN profile_info i ON i.info_userId = v.visitor_accountId
GROUP BY v.visitor_accountId
ORDER BY v.visitor_date DESC
LIMIT 1
I've tried to get last entry with this query but I just can't get last row (only the first):
select users.*,messages.*
from messages
LEFT JOIN users
ON messages.messageBy=users.email
where messageToUser='{loginUser}'
GROUP BY messageBy
If you want to get last record with group by then try the below query
select users.*,message.*
from
message
LEFT JOIN
users
ON
message.messageBy = users.email
where
messageToUser=1
AND
messageid IN (SELECT max(messageid) FROM message GROUP BY messageBy)
GROUP BY
messageBy
ORDER BY
messageid DESC
rough demo at http://sqlfiddle.com/#!2/cda6f/1
So, if you have any kind of id field or date stored in your message table, you could do:
SELECT
...
ORDER BY your_date_field DESC
LIMIT 1
OR
SELECT
...
ORDER BY id DESC
LIMIT 1
Otherwise you are left with using code to count the number of records returned and just get the last one.
Oh, you want the last message from each user.
A stock solution looks like this...
SELECT x.*
FROM my_table x
JOIN (SELECT my_grouping_id,MAX(my_ordering_id) max_my_ordering_id FROM my_table GROUP BY my_grouping_id) y
ON y.my_grouping_id = x.my_grouping_id
AND y.max_my_ordering_id = x.my_ordering_id;
I am saving the history of Facebook likes for a page, identified by user_id.
Now from this table, I need to get a set representing the user_id's and their latest number of likes, based on the most recent timestamp.
I started off with this:
SELECT *
FROM facebook_log
GROUP BY user_id
ORDER BY timestamp DESC;
But that does not do what I want because it returns the first records with the lowest timestamps.
I read something online about GROUP returning the very first records from the table.
I also understood something about JOIN the table with itself, but that doesn't work either, or I did something wrong.
If you just need the user_id and the timestamp, you can just do
select f.user_id, max(f.timestamp)
from facebook_log
group by user_id;
if you need all the data from the table, you can do
select f.*
from facebook_log f
inner join (select max(timestamp) mt, user_id
from facebook_log
group by user_id) m
on m.user_id = f.user_id and m.mt = f.timestamp
You can also get the latest number of likes by using this MySQL trick:
select f.user_id, max(f.timestamp),
substring_index(group_concat(f.numlikes order by f.timestamp desc), ',', 1) as LatestLikes
from facebook_log f
group by f.user_id;