MySQL Max statement not returning result - mysql

I have the following MySQL statement
SELECT * FROM user_messages AS T WHERE user_id = '33' AND id = (SELECT Max(id) from user_messages AS TT WHERE T.from_userid = TT.from_userid) ORDER BY status, id DESC
The problem I seem to be having is when I only have one record. I would think that MySQL would return the single record associated with user_link = '33', but instead it returns nothing.
I need to use the "Max" function because I use it to pull the most recent entries. I am trying to avoid having multiple queries or having to use php to sort also. Any help much appreciated!

This is your query:
SELECT *
FROM user_messages AS T
WHERE user_id = '33' AND
id = (SELECT Max(id)
from user_messages AS TT
WHERE T.from_userid = TT.from_userid
)
ORDER BY status, id DESC
Here are three reasons it could be failing to return any rows. First, user_id = '33' may not exist in the table. Second from_userid may be NULL. Third, the id value may be NULL for all matching records.
Perhaps this simpler version would help:
select *
from user_messages um
where user_id = '33'
order by id desc
limit 1

Thanks for your answer Gordon, I checked the database, and the record exists. I did some more research, and what it turns out to be is that I needed to join the data. I was able to return the Min or Max record, but the corresponding/related fields weren't returned with it.
SELECT * FROM user_messages INNER JOIN(SELECT from_username, MAX(id) AS id FROM user_messages WHERE user_link = '33' GROUP BY from_username ORDER BY status, id DESC) t2 ON user_messages.id = t2.id AND user_messages.from_username = t2.from_username
The thread that answered the question was this one - Need To Pull Most Recent Record By Timestamp Per Unique ID

Related

Subquery using UNION ALL in MySQL

I guess I don't understand the order in which subqueries work.
When I run this SQL statement I get 1 (out of 3 that exist in the table) random 'friend id' :
SELECT t1.sender_id AS Connections FROM
(SELECT DISTINCT sender_id
FROM connection
WHERE receiver_id = 'my_id'
AND status = 'Approved') t1
UNION ALL
SELECT t2.receiver_id FROM
(SELECT DISTINCT receiver_id
FROM connection
WHERE sender_id = 'my_id'
AND status = 'Approved') t2
ORDER BY RAND() LIMIT 1;
One random id is returned which is what I want.
BUT when I wrap the previous SQL statement within another SQL statement to get the friend's name and id (from the id in sub-query) the results come back randomly as either empty or 1 friend or 2 friends or all 3 friends :
SELECT id, name FROM profile
WHERE id = (
SELECT t1.sender_id AS Connections FROM
(SELECT DISTINCT sender_id
FROM connection
WHERE receiver_id = 'my_id'
AND status = 'Approved') t1
UNION ALL
SELECT t2.receiver_id FROM
(SELECT DISTINCT receiver_id
FROM connection
WHERE sender_id = 'my_id'
AND status = 'Approved') t2
ORDER BY RAND() LIMIT 1);
I want it to emit the same behaviour as the first code snippet.
The problem is that the subquery is being re-executed for every row being tested in profile. Each time it returns a different random ID; if that ID happens to match the current row of profile, the row is returned.
Instead of using WHERE id =, use a JOIN. This will just run the subquery once.
SELECT p.id, p.name
FROM profile AS p
JOIN (
SELECT t1.sender_id AS Connections FROM
(SELECT DISTINCT sender_id
FROM connection
WHERE receiver_id = 'my_id'
AND status = 'Approved') t1
UNION ALL
SELECT t2.receiver_id FROM
(SELECT DISTINCT receiver_id
FROM connection
WHERE sender_id = 'my_id'
AND status = 'Approved') t2
ORDER BY RAND() LIMIT 1) AS r
ON p.id = r.Connections
Are you really asking for all the sender_ids and one receiver_id?
It feels like you have an extra layer of SELECTs.
When in doubt, add extra parentheses:
( SELECT ... )
UNION ALL
( SELECT ... ORDER BY ...) -- this ORDER BY applies only to the select
ORDER BY ... -- This applies to the result of the UNION, not the second select

SQL Inner join with limit on subquery not to affect query

I'm running a query in MySQL with an INNER JOIN that has a LIMIT on the subquery
The problem is, that the LIMIT on the subquery is affecting the number of rows returned.
I want to select all rows from table 1 (tickets) where the last row in ticket_updates relevant (t.ticketnumber = tu.ticketnumber) was not numeric in column contact_name
SELECT t.*
FROM tickets t
JOIN
( SELECT ticketnumber
FROM ticket_updates
WHERE type = 'update'
AND concat('', contact_name * 1) <> contact_name
ORDER
BY sequence DESC
LIMIT 1
) tu
ON t.ticketnumber = tu.ticketnumber
WHERE t.status <> 'Completed'
AND LOWER(t.department) = 'support';
But the results shown just return the 1 row
There are multiple rows in ticket_updates that relate to each row in tickets based on tickets.ticketnumber =ticket_updates.ticketnumber`
the contact_name column can either be a string or integer. I picked up the concat('', contact_name * 1) <> contact_name from another SO Post which tells me whether the value is numeric or not.
So I want to pick up the latest row (ORDER BY sequence DESC) in ticket_updates for each row in tickets and see whether contact_name is not numeric
Your query selects one row because (as you concluded yourself) your subquery is limited to one result.
what you want is probably something similar to what can be found in this answer (I assumed that you want the entry with biggest value for sequence, if the contratry, change to MIN)
with a subquery (there should be an adaptation from the shortest more optimized query in the cited answer, but let's see if this one works first):
SELECT t.*
FROM tickets t
INNER JOIN ( SELECT ticketnumber, MAX(tu.sequence) AS maxSequence
FROM ticket_updates tu
WHERE tu.type = 'update' AND concat('', tu.contact_name * 1) <> tu.contact_name
GROUP BY ticketnumber ) tu2
ON (t.ticketnumber = tu2.ticketnumber)
WHERE t.status <> 'Completed'
AND LOWER(t.department) = 'support';
see it in action

Combine subqueries used to retrieve values for comparison into a single query?

I have an SQL query like this:
SELECT COUNT(*) AS count_value FROM submissions WHERE username = (
SELECT username FROM submissions WHERE id = '1'
) AND number = (
SELECT number FROM submissions WHERE id = '1'
) AND tstmp < (
SELECT tstmp FROM submissions WHERE id = '1'
);
Notice how I am using this query to find all rows with similar column values, but with a timestamp value that is less than row number 1.
This works for me, but I was wondering, is there a way I could combine the three subqueries into one? They all select information from the same table, so I thought it might be possible, but I have no clue how to do it.
I think you could merge the subqueries into one and use it as a derived table in a join. Please try this:
SELECT COUNT(*) AS count_value
FROM submissions s
JOIN (
SELECT username, number, tstmp
FROM submissions WHERE id = 1
) o ON s.number = o.number AND s.username = o.username AND s.tstmp < o.tstmp

Best practice to get newest row in a table

Consider a table like this:
The id column is set to auto-increment, update_time column is supposed to be the date that the row was inserted in the table.
I want to simply get the latest entry for a user with user_id = x, I found out there are some ways:
SELECT * FROM mytable WHERE user_id = x ORDER BY update_time DESC LIMIT 1
And
SELECT * FROM mytable WHERE user_id = x MAX(update_time)
And another query would be selecting the row with highest id number
I am not quite sure about the syntax of the later one (please correct me).
This may seem to be a trivial task, but there was a case that someone else has altered the auto_increment value on the table, and sometimes the time of the server has changed (well this has not been happened in my case but what if it does!!?)
What would be the safest query to get the latest entry row for a user_id ( I mean a query to return weigh, height and activity_level for a user with user_id = x)
Do I need to add more columns to the table? if so, what?
I like the join approach for this. Assumes that userID + update_time is unique...it'll pull back multiple rows if it isn't.
select user_id, max(update_time) maxtime from table group by user_id
Simple statement to get the max update time by user ID. Use it as a subquery with inner join (inner join will function as a filter)
select t.*
from table t
inner join
(select user_id, max(update_time) maxtime
from table group by user_id
--where user_id = x
)a
on a.user_id = t.user_id and a.maxtime = t.update_time
I commented out the where user_id = x line...the advantage to this method is you can get all users and their most recent at once.
SELECT * FROM mytable WHERE user_id = x AND update_time = (SELECT MAX(update_time) FROM mytable WHERE user_id = x)
This really does not have to be so complicated:
SELECT id
FROM table
WHERE user_id = x
ORDER BY update_time DESC
LIMIT 1
This version will be the quickest, simplest, and easiest to read. It is a win in every regard.

Mysql: Update field of most latest record

I'm trying to update the latest record where name is John (John has multiple records but different ID) but I seem to be in a bind. What's wrong with my query?
UPDATE messages_tbl SET is_unread=1
WHERE ReceiveTime = (SELECT MAX(ReceiveTime) FROM messages_tbl WHERE name='John')
Is there a better way to do something like this?
You could try using ORDER and LIMIT.
Try this:
UPDATE messages_tbl SET is_unread = 1
WHERE name = 'John'
ORDER BY ReceiveTime DESC
LIMIT 1
This query will update the rows in order of the highest (most recent) ReceiveTime to the lowest (oldest) ReceiveTime. Used in conjunction with LIMIT, only the most recent ReceiveTime will be altered.
You can join both and perform update based on the condition.
UPDATE messages a
INNER JOIN
(
SELECT name , MAX(ReceiveTime) max_time
FROM messages
GROUP BY name
) b ON a.name = b.name AND
a.ReceiveTime = b.max_time
SET a.is_unread = 1
-- WHERE a.name = 'John'
Without the WHERE condition. It will all update the column is_unread for the latest entry.