ORDER BY before GROUP BY - mysql

I have a page showing a list of persons with whom you have been chatting to. Currently it's showing the persons you have been chatting to, and the OLDEST message. However, it should show the NEWEST message. This is the query:
SELECT * FROM post
WHERE fk_user_to = '$userid'
GROUP BY fk_user_from
ORDER BY datotime DESC
and the table structure
post_id || fk_user_to || fk_user_from || message || datotime

This worked out:
SELECT * FROM
(SELECT * FROM post ORDER BY datotime DESC) as inv
WHERE fk_user_to = '$userid'
GROUP BY fk_user_from
ORDER BY datotime DESC

There is no simple solution with plain SQL I think. If your database system allows subqueries, you got do a subquery like
SELECT fk_user_from AS id, MAX(dateotime) AS newest_timestamp FROM post WHERE fk_user_to = '$userid'
and then select from post again using the two fields as key.
In MySQL that could be something like:
SELECT * FROM post P1
JOIN (
SELECT fk_user_from, MAX(dateotime) AS newest_dateotime
FROM post
WHERE fk_user_to = '$userid'
GROUP BY fk_user_from
) AS P2
ON P1.fk_user_from=P2.fk_user_from
AND P1.datotime =P2.newest_dateotime
WHERE P1.fk_user_to = '$userid'

It doesn't really work like that. You can never be sure what row GROUP BY selects, so putting an ORDER BY on it will have unpredictable output. Also you cannot put an order by BEFORE a GROUP BY.
Try this:
SELECT *,MAX(datotime) AS dt fk_user_from
FROM post
WHERE fk_user_to = '$userid'
GROUP BY fk_user_from
ORDER BY dt

Related

order by and group by both at time not working

My query is below
SELECT *
FROM
(
SELECT
usr.*,
messages.message_text, messages.message_id
FROM
`user` as usr
LEFT JOIN
(
SELECT
message.*
FROM
message AS message
ORDER BY
message.updated_at
DESC
) AS messages
ON
`usr`.`user_id` = `messages`.`sender_id` OR `usr`.`user_id` = `messages`.`receiver_id`
WHERE
`usr`.`is_delete` = 0 AND `usr`.`is_active` = 1
ORDER BY
messages.updated_at
DESC
) AS result
GROUP BY
result.user_id
if i remove the group by then it work well , but i want the result with group by Please Help.
I have one message table in that i have saved the sender id and receiver id, both id have foreign key with user table and i want the recent message send by user and user details
So for latest message i am using order by desc and after getting all the messages with descending order i am using group by but it is not working.
It was very hard making the table schemas and the data insert in them which would act like your scenario. So next time, please provide a fiddle link to your schema/situation.
Here were the issues in your query:
You dont need a subquery after LEFT JOIN
ORDER BY clause is always after GROUP BY
You must mention all the columns that you are SELECTing in the GROUP BY clause.
Tweaked your query a bit:
SELECT *
FROM
(
SELECT
usr.*,
messages.message_text, messages.message_id, messages.updated_at
FROM
user as usr
LEFT JOIN message messages
--(
-- SELECT
-- message.*
-- FROM
-- message AS message
-- ORDER BY
-- message.updated_at
-- DESC
--) AS messages
ON
usr.user_id = messages.sender_id OR usr.user_id = messages.receiver_id
WHERE
usr.is_delete = 0 AND usr.is_active = 1
--ORDER BY
--messages.updated_at
--DESC
) AS result
GROUP BY
result.user_id,result.name,result.is_delete,result.is_active,result.message_text,result.message_id,updated_at
ORDER BY
result.updated_at
DESC
Hope it helps :)

MySQL (Hottest) SORT BY 2 different parameters(Most liked in less time)

I have been trying to figure out how to make "Hottest Posts" where posts are selected ordering by most upvoted in shortest time.
I have got 2 database tables:
fun_posts:
fun_post_upvotes:
And latest of my code, that still dosn't work:
$stmt = $this->conn->prepare("SELECT * FROM fun_posts, (SELECT image_id, COUNT(*) FROM fun_post_upvotes GROUP BY image_id)
WHERE id = image_id ORDER BY id DESC, upvotes DESC");
Try it with this query:
$stmt = $this->conn->prepare=("SELECT * , (SELECT COUNT(*)
FROM fun_post_upvotes
WHERE image_id=fun_posts.id
GROUP BY image_id)
FROM fun_posts
ORDER BY fun_posts,id DESC, fun_posts.upvotes DESC");

Mysql- Select Query from two table

I have two table item_info and item_log tables are given below:
Now i need to search by 'like' item_name and the result will show last row of any item_id like:
can you try something like this:
SELECT table1.*, MAX( table1.id ) AS last_id,
table2.table2.id
FROM (table1)
JOIN table2 ON table1.table2.id = table2.table2.id
WHERE item_name LIKE '%nameOfItem%'
GROUP BY table1.table2.id
ORDER BY table1.id desc
it's kinda same with my function, i have to retrieve recent message for every thread. so i have to join the tables and group it by message id, and in the descending order in which the message has sent.
basically, the logic is quite the same. let me know if it doesn't work
Problem Solved
SELECT item_log.*,item_info.name
FROM (item_log)
JOIN item_infos ON item_log.item_id = item_infos.item_id
WHERE id IN (SELECT MAX( item_log.id )
FROM (item_log)
JOIN item_infos ON item_log.item_id = item_infos.item_id
WHERE item_name LIKE '%G%'
GROUP BY item_log.item_id
ORDER BY item_log.id desc)
AND item_name LIKE '%G%'
GROUP BY item_log.item_id
ORDER BY item_log.id desc
SELECT
*
FROM
(SELECT
item_info.`item_name`,
item_log.`item_id`,
item_log.`id`,
item_log.`item_barcode`,
item_log.`buy_price`
FROM
item_log,
item_info
WHERE item_info.`item_id` = item_log.`item_id`
ORDER BY id DESC) AS i
GROUP BY item_id ;
I think this is what you are expecting right ?
This may work for you:
SELECT l.id,i.item_id,l.item_barcode,i.item_name,l.buy_price
FROM item_info i
LEFT JOIN item_log l ON i.item_id=l.item_id
WHERE i.item_name LIKE '%G%'
ORDER BY l.id desc

Latest results from db

I need display results from two joined tables only for the latest project. I have the following query:
SELECT project.id,
project.created,
COUNT(DISTINCT events.user_id) AS cnt
FROM project
JOIN events ON (events.project_id = project.id)
WHERE project.creator = $creatorID
AND events.user_id != $creatorID
ORDER BY project.created DESC
LIMIT 1
For some reason I keep on getting the first project... What am I missing here?
You're definitely on the right track. It seems you're missing a GROUP BY clause for your aggregate COUNT(). Try this:
SELECT
project.id,
project.created,
count(DISTINCT events.user_id) AS cnt
FROM project
JOIN events ON (events.project_id = project.id)
WHERE
project.creator = $creatorID
AND events.user_id != $creatorID
GROUP BY project.id, project.created
ORDER BY project.created DESC,
LIMIT 1

How do I get more than one column from a SELECT subquery?

Here is my problem :
I have 3 tables : account, account_event and account_subscription
account contains details like : company_name, email, phone, ...
account_event contains following events : incoming calls, outgoing calls, visit, mail
I use account_subscription in this query to retrieve the "prospects" accounts. If the account does not have a subscription, it is a prospect.
What I am using right now is the following query, which is working fine :
SELECT `account`.*,
(SELECT event_date
FROM clients.account_event cae
WHERE cae.account_id = account.id
AND cae.event_type = 'visit'
AND cae.event_done = 'Y'
ORDER BY event_date DESC
LIMIT 1) last_visit_date
FROM (`clients`.`account`)
WHERE (SELECT count(*)
FROM clients.account_subscription cas
WHERE cas.account_id = account.id) = 0
ORDER BY `last_visit_date` DESC
You can see that it returns the last_visit_date.
I would like to modify my query to return the last event details (last contact). I need the event_date AND the event_type.
So I tried the following query which is NOT working because apparently I can't get more than one column from my select subquery.
SELECT `account`.*,
(SELECT event_date last_contact_date, event_type last_contact_type
FROM clients.account_event cae
WHERE cae.account_id = account.id
AND cae.event_done = 'Y'
ORDER BY event_date DESC
LIMIT 1)
FROM (`clients`.`account`)
WHERE (SELECT count(*)
FROM clients.account_subscription cas
WHERE cas.account_id = account.id) = 0
ORDER BY `last_visit_date` DESC
I tried a lot of solutions around joins but my problem is that I need to get the last event for each account.
Any ideas?
Thank you in advance.
Jerome
Get a PRIMARY KEY in a subquery and join the actual table on it:
SELECT a.*, ae.*
FROM account a
JOIN account_event ae
ON ae.id =
(
SELECT id
FROM account_event aei
WHERE aei.account_id = a.id
AND aei.event_done = 'Y'
ORDER BY
event_date DESC
LIMIT 1
)
WHERE a.id NOT IN
(
SELECT account_id
FROM account_subscription
)
ORDER BY
last_visit_date DESC
Try moving the subquery to from part and alias it; it will look as just another table and you'll be able to extract more than one column from it.