MySQL GROUP BY and Descending - mysql

I've been trying to gather some data from a MySQL database for a while now.
The problem is that I want to group the data by objectid while getting only the newest data (Descending).
Everytime I try it, I either get an error, or it doesnt Descend.
My query at the moment is:
SELECT * FROM 'table' GROUP BY 'objectid' DESC
I've tried ordering by id or timestamp, but with an ascended result.
My question is similar to: http://stackoverflow.com/questions/7306082/mysql-using-group-by-and-desc
However the answers provided there didn't solve my problem.
Thanks in advance!

You also have to specify ORDER BY clause for sorting:
SELECT * FROM 'table' GROUP BY 'objectid' ORDER BY timestamp DESC

your query is wrong you should make backticks instead of single quotes
and you missed order by statment
try this
SELECT * FROM `table` GROUP BY `objectid` Order by id DESC

This will give you the most recent entry per ObjectId, ordered by descending time; it simply left joins to find all entries where there exists no newer entry for the same ObjectId.
SELECT a.*
FROM table1 a
LEFT JOIN table1 b
ON a.ObjectId=b.ObjectId
AND a.time < b.time
WHERE b.ObjectId IS NULL
ORDER BY time DESC
An SQLfiddle to test with.

Related

The last value using GROUP BY

I need to take the last value from table where can_id equal.
So I've tried this SQL query
SELECT com.text, com.can_id
FROM (SELECT * FROM comments ORDER BY id DESC) as com
GROUP BY com.can_id
But if I change ASC / DESC in the first select, the second select will just group without sorting and take the value with the first id
This select will be used like left join in the query.
Example:
I need to get com.text with value "text2" (lasts)
If you are on MySql 8, you can use row_number:
SELECT com.text, com.can_id
FROM (SELECT comments.*,
row_number() over (partition by can_id order by id desc) rn
FROM comments) as com
WHERE rn = 1;
If you are on MySql 5.6+, you can (ab)use group_concat:
SELECT SUBSTRING_INDEX(group_concat(text order by id desc), ',', 1),
can_id
FROM comments
GROUP BY can_id;
In any version of MySQL, the following will work:
SELECT c.*
FROM comments c
WHERE c.id = (SELECT MAX(c2.id)
FROM comments c2
WHERE c2.can_id = c.can_id
);
With an index on comments(can_id, id), this should also have the best performance.
This is better than a group by approach because it can make use of an index and is not limited by some internal limitation on intermediate string lengths.
This should have better performance than row_number() because it does not assign a row number to each row, only then to filter things out.
The order by clause in the inner select is redundant since it's being used as a table, and tables in a relational database are unordered by nature.
While other databases such as SQL Server will treat is as an error, I guess MySql simply ignores it.
I think you are looking for something like this:
SELECT text, can_id
FROM comments
ORDER BY id DESC
LIMIT 1
This way you get the text and can_id associated with the highest id value.

MySQL 5.7 How to do GROUP BY with sorting?

Similar to this issue: MySQL 5.7 group by latest record
I'm not sure how to do this properly in 5.7. Also with possibility of 2nd sort column. Working query in 5.6 that I'm trying to replicate in 5.7:
SELECT id FROM test
GROUP BY category
ORDER BY sort1 DESC, sort2 DESC
id is not always the highest, so MAX(id) does not work.
Looking into the link above, the solution for single sort should be:
SELECT t1.*
FROM test t1
INNER JOIN (
SELECT category, max(sort) AS sort FROM test GROUP BY category
) t2 ON t2.category = t1.category AND t2.sort = t1.sort
But how will it work with 2 sorting?
You are using GROUP BY the wrong way.
Think of group by as a way to separate data row into different groups. Each group has multiple rows, based on the value of group by column.
Once you get those groups, selecting table columns (as in: select *) is like picking any row from that group randomly. This is not helpful nor useful.
Usually once we group records (or rows), we need to find meta information about those records. For example: get us the count of records in that group (as in: select count(*)), or the sum of values of a specific column in that group (as in: select sum(price)), or get the min, max or avg values.
So in a nutshell, when you use group by you should use on of the aggregation functions with it, otherwise it's not going to do you any good.
Why don't you have the ORDER BY at your outer query, instead?
SELECT *
FROM (
SELECT 100 AS id, 1 AS category, NULL AS sort
UNION
SELECT 200 AS id, 1 AS category, 2 AS sort
) dt
GROUP BY category
ORDER BY sort DESC;
It seems that what happened to the data when it was grouped, it took the first data while neglecting the ORDER BY DESC. On your first query, it ordered descending first then group by took the first record which is 200. And yes, this shouldn't be the way you should use GROUP BY. It is used in conjunction with aggregate functions.
when you select a column in a group by query that is not one of the columns you are grouping by, (ie, your id) you have no control over the value unless you use another aggregate function. If you want to sort, use MIN or MAX:
SELECT MAX(id), category, FROM `test2`
GROUP BY category; -- always returns 200
SELECT MIN(id), category, FROM `test2`
GROUP BY category; -- always returns 100

mysql result with order by is different from order by and limit

I have a table A with columns id, age.
Two queries below return different result and I don't know why:
SELECT distinct a.id id FROM A a ORDER BY a.age DESC
SELECT distinct a.id id FROM A a ORDER BY a.age DESC LIMIT 10 OFFSET 0
Any ideas? I would expect the second query to return the first 10 results of the first query.
EDIT:
What I forgot to say is that there are rows with the same age. So I think it has something to do with it.
I am surprised they work. In most databases you would get a syntax error, because a.age is not in the select. I know that MySQL extends the GROUP BY to allow the use of un-aggregated columns. I presume it has the same reasoning for SELECT DISTINCT. That is, age comes from an indeterminate row for each id. It is so indeterminate that it might change from one query to another.
Here are two appropriate ways to write the query:
SELECT distinct a.id, a.age
FROM A a
ORDER BY a.age DESC;
or:
SELECT a.id
FROM A a
ORDER BY MIN(a.age) DESC; -- Or perhaps MAX(a.age) or AVG(a.age)
These should have more stable results, with or without the LIMIT.
Found a solution.
I'm not sure why it's happening. I'm using mysql and maybe the implementation of the query when adding limit is different from when without it.
Any way, I added in the ORDER BY a.id. This kept the order when adding limit.
So this is how the query looks:
SELECT distinct a.id id FROM A a ORDER BY a.age DESC, a.id LIMIT 10 OFFSET 0

Shortest way to GROUP BY similar values and retain latest rows?

Sometimes I want to get just one row of each similar value, I ussually do somethingl ike this:
SELECT * GROUP BY Text ORDER BY Date DESC
My problem using GROUP to select similar rows is that I don't get the values from the latest rows in the row (I'm not quite sure what's the criteria to choosing the row that stays). I want to retain only the newest row in the group.
I know how to do it with a self join but when statements are already very long it seems a bit complicated. Is there any shorter method? Maybe using DISTINCT instead of GROUP BY?
Assuming you have a table that has multiple columns and two of which are GroupID and DATE. If you want to select the latest record for each GroupID, you need to have a subquery which gets the latest Date for each GroupID, example
SELECT a.* -- this just selects all records from original table
FROM tableName a
INNER JOIN
(
-- this subquery gets the latest DATE entry for each GROUPID
SELECT GroupID, MAX(DATE) maxDate
FROM tableName
GROUP BY GroupID
) b ON a.GroupID = b.GroupID AND
a.Date = b.maxDate
if this answer is not clear, please do ask :D
Did you try to use the max function:
SELECT A,B,max(Date) GROUP BY Text

MySQL - using GROUP BY and DESC

In my SQL query I am selecting data with GROUP BY and ORDER BY clauses. The table has the same numbers across multiple rows with different times in each row. So I think I want to apply a GROUP BY clause.
However in the results return the oldest time with the number, but I need the most recent time.
SELECT * FROM TABLE GROUP BY (numbers) ORDER BY time DESC
The query appears as if it should first apply GROUP BY and then ORDER BY... but the results do not appear to work this way.
Is there any way to fix this?
SELECT *
FROM table t
WHERE time = (
SELECT max(time)
FROM table
WHERE t.numbers = numbers
)
work-around is to re-write the query as:
SELECT * FROM (SELECT * FROM table ORDER BY time DESC) AS t GROUP BY numbers;
SELECT * FROM table
WHERE time IN (
SELECT MAX(time)
FROM table
GROUP BY numbers
)
According to the manual you can add desc to the group by list:
Example:
group by item1, item2 desc, item3
with or without rollup.
I've tried this and it works in Ubuntu version 5.5.58. The reference page is:
https://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html
SELECT * FROM TABLE GROUP BY numbers DESC;
This will give you last record from group.
Thanks