Get most recent ROW with a GROUP BY on multiple columns - mysql

I'm trying to get the most resent result for every amount linked to a duration.
This is my table :
SELECT * FROM financement;
id amount duration total
8 200 5 result8
7 200 4 result7
6 100 5 result6
5 100 4 result5
4 200 5 result4
3 200 4 result3
2 100 5 result2
1 100 4 result1
There is is a total for every amount linked to a duration.
My problematic is that, they can be multiple row for the same amout x duration and I only want the most recent.
For exemple in my case :
id amount duration total
5 100 4 result5
1 100 4 result1
I tried to use a GROUP BY like this:
SELECT * FROM `financement` GROUP BY amout, duration ORDER BY `id` DESC
But with this method, even with the ORDER BY id DESC, I still get the most ancien ROW.
I also tried to SELECT max() in a sub query like this, but the query is extremely long and it times out.
SELECT * financement where id in (select max(id) from financement group by amount, duration);
How can I get this output ?
id amount duration total
8 200 5 result8
7 200 4 result7
6 100 5 result6
5 100 4 result5

This should work:
SELECT * FROM `financement`
WHERE id IN (
SELECT max(id) as id FROM `financement` GROUP BY duration, amount
)
ORDER BY `id` DESC

I think you want filtering. You can use a scalar subquery:
select f.*
from financement f
where f.id = (select max(f2.id)
from financement f2
where f2.amount = f.amount and f2.duration = f.duration
);

Try this query:
SELECT * FROM financement ORDER BY id DESC
output of this query

Related

SELECT rows with MAX id minus 1 with group by

I have a table with id, city_id, and stock which looks like this.
id
city_id
stock
1
1
1000
2
2
500
3
3
11000
4
2
600
5
3
12000
6
1
2000
9
3
13000
10
1
3000
11
1
4000
12
2
700
To select the latest stock values for each city_id I used the following query, which works fine.
SELECT `stock`
FROM `stock_table`
WHERE id in ( SELECT MAX(id)
FROM `stock_table`
GROUP BY city_id
);
It returns
stock
13000
4000
700
Now I want to select 2nd latest stock entry for each city_id. So the output should be like the following table.
stock
12000
3000
600
Any help is greatly appreciated. Thanks!
In MySQL 8 you can use the row_number() window function to assign a number to each row ordered by the id per partition of city_id. Then just filter on that being 2 (in your example; you can use any number).
SELECT x.stock
FROM (SELECT s.stock,
row_number() OVER (PARTITION BY s.city_id
ORDER BY s.id DESC) rn
FROM stock_table s) x
WHERE x.rn = 2;
u can use group by with row number and get rownumber 2
ROW_NUMBER() OVER (PARTITION BY city_id ORDER By id) as ROW

need help to find number of times a number is repeated in query result

I have a table like following
item_id link_id
1 10
1 20
2 100
2 40
2 10
3 10
3 30
4 10
4 20
4 30
I ran the query to find occurrence of each item_id
select `item_id`, count(`item_id`)
from `table`
group by `order_id`
which gave me the result
item_id count('item_id')
1 2
2 3
3 2
4 3
But I have to find out how many time did i had each value in result, something like this
count('item_id') Occurence
2 2
3 2
How should I update the query
Use two levels of aggregation:
select cnt, count(*), min(item_id), max(item_id)
from (select `item_id`, count(`item_id`) as cnt
from `table`
group by `order_id`
) i
group by cnt;
I also often add min(item_id), max(item_id) to such queries to get examples for each count.

How to select only last rows that satisfies conditions?

I'm trying to select rows where x=5, but x changes constantly. So I have such a table:
id x
---- ---
1 5
2 6
3 4
4 5
5 5
So I want to perform a query like "SELECT * FROM table WHERE x=5 AND _???_;" so that it returns rows 4 & 5 but not row 1.
In other words, I want to get the rows where x had this value most recently. I hope I made myself clear. Thanks!
edit:
Number of entries after x got the last value my change. I mean the table could also be like this:
id x
---- ---
1 5
2 6
3 4
4 5
5 1
6 5
7 5
... 5
100 5
101 5
in this case it should return rows [6-101].
Following wil get recent row
SELECT * FROM table WHERE x=5 ORDER BY id DESC LIMIT 0,1
SQLFiddle demo
select * from t t1
where
x=(select x from t order by id desc limit 1)
and
not exists
(select x from t where id>t1.id and x<>t1.x)
or
SQLFiddle demo
select * from t t1
where
x=(select x from t order by id desc limit 1)
and
id>=
(select max(id) from t
where x<>
(select x from t order by id desc limit 1)
)
Select what is faster on your base.

id order is mixed while using order by

I am using MySQL as a database.
Now I got everything working correctly but as my client wants to have filter on the website I am in the some sort of problem of what exactly I need to do and what would be the best way of doing it.
So this is my data ( I will simplify it as much as possible )
id name price nr.bed nr.bath
---------------------------------
1 a 33 2 4
2 b 100 5 1
3 c 102 2 2
4 d 85 1 1
5 e 37 6 4
6 f 19 2 1
So first time page loads I am using this query to get first 5 from the database:
SELECT * FROM hotel LIMIT 5
And I get this:
id name price nr.bed nr.bath
---------------------------------
1 a 33 2 4
2 b 100 5 1
3 c 102 2 2
4 d 85 1 1
5 e 37 6 4
After that each time I am calling this:
SELECT * FROM hotel WHERE id>'last_id(in this case 5)' LIMIT 5
And I am getting:
id name price nr.bed nr.bath
---------------------------------
6 f 19 2 1
And so on...
But now I need to use filter for example I will have filter for price
So I need to have something like:
SELECT * FROM hotel where id>5 order by price desc LIMIT 5
But then I am loosing my id order and I can't get next five from the database because I can't compare to and id of hotel because everything is orderd by price.
How can I achieve this?
Do I need to add another column or something which will keep my order as it is? Everything is presented on the website using and id from the table.
EDIT:
I am not sure if that is even possible because I need to have id ordered in asc and price in desc but I am not sure if we can combine those two together without adding another column or something.
EDIT2:
I would like to get something like this
id id_copy name price nr.bed nr.bath
-----------------------------------------
1 3 c 102 2 2
2 2 b 100 5 1
3 4 d 85 1 1
4 5 e 37 6 4
5 1 a 33 2 4
6 6 f 19 2 1
First, you should never use limit without order by when the ordering is important. Your queries should be like:
SELECT *
FROM hotel
WHERE id>'last_id(in this case 5)'
ORDER BY id
LIMIT 5
For your question, you want a subquery:
select *
from (SELECT * FROM hotel where id>5 order by price desc LIMIT 5
) t
order by id
The inner query selects the 5 by price. The outer one orders by id.
If you want to use this for "pagination", then you should become familiar with the offset argument to limit. This is described in the MySQL documentation here.
Order two columns then:
SELECT * FROM hotel where id>5 order by price desc , id asc LIMIT 5
i think this what you are looking for
SELECT * FROM hotel order by price desc limit 0 ,5
then if you want next 5
SELECT * FROM hotel order by price desc limit 5 ,5
then
SELECT * FROM hotel order by price desc limit 10 ,5
and so on...
you can make this in php like that
$sql="SELECT * FROM hotel order by price desc "
if (sombutton is clicked) {
$sql .= " limit 0,5" ;}
if (sombutton is clicked){
$sql .= " limit 5,5" ; }
or you can do it by a loop with variable $i everytime you add 5.

MySQL Query limit 3 or more if last 3 are equal?

I need to limit my result to 3 row (an example), but if 3rd result is equal to 4th, print also 4th, and so on.
To explain: from this table
id punteggio
1 100
2 200
3 70
4 100
5 54
6 201
7 200
if I do
SELECT * FROM table ORDER BY punteggio DESC LIMIT 3
i need in every case to print following situation:
id punteggio
6 201
2 200
7 200
1 100
4 100
Because my "three" best points are in reality 5 of 7, cause 2 and 7 have same points, like 1 and 4...
I dont'know in advance min and max points, otherwise i would do
"WHERE punteggio >= 100"
Thank you very much!
UPDATE
Unfortunately my scenario changed:
punteggio born from SUM from another table:
id idPersona punteggio
1 1 30
2 1 -10
3 2 50
4 3 60
5 2 -10
6 3 150
7 1 190
and so on...
i've tried do:
SELECT persone.nome,
SUM(transazioni.importoFinale) AS punti
FROM transazioni
INNER JOIN persone ON persone.idPersona = transazioni.idPersona
INNER JOIN
(SELECT DISTINCT(SUM(transazioni.importoFinale)) AS punti,
persone.nome
FROM transazioni
INNER JOIN persone on persone.idPersona = transazioni.idPersona
GROUP BY persone.idPersona
ORDER BY punti DESC
LIMIT 3) subq ON transazioni.punti = subq.punti
ORDER BY punti DESC
but it doens't function...
Thank you to all!
Use a subquery join to get the DISTINCT set of 3 greatest values for punteggio and join it against the main table to retrieve all rows that have those values.
SELECT
id,
punteggio
FROM
yourtable
/* subquery gets the top 3 values only */
/* and the INNER JOIN matches it to all rows in the main table having those values */
INNER JOIN (
SELECT DISTINCT punteggio as p
FROM yourtable
ORDER BY punteggio DESC
LIMIT 3
) subq ON yourtable.punteggio = subq.p
ORDER BY punteggio DESC
Here's a demo on SQLFiddle.com
SELECT id, punteggio
FROM yourtable
WHERE punteggio IN (
SELECT * FROM (
SELECT DISTINCT punteggio
FROM yourtable
ORDER BY punteggio DESC
LIMIT 3
) AS temp
);
Note that the select * is present to work around mysql not supporting limits in subqueries in an IN() clause.