SELECT rows with MAX id minus 1 with group by - mysql

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

Related

How to find which number of orders for a customer

Given a table orders
id
customer_id
created_at
1
1
2022-09-01
2
2
2022-09-02
3
1
2022-09-03
4
1
2022-09-04
5
2
2022-09-04
How do I produce a column that describes which number in the series for the customers the order is?
Example
id
customer_id
created_at
order number
1
1
2022-09-01
1
2
2
2022-09-02
1
3
1
2022-09-03
2
4
1
2022-09-04
3
5
2
2022-09-5
2
You can use a window function for that. With a cumulative count over a partition by customer id, you get exactly the order number you need:
select orders.*,
count(*) over (partition by customer_id order by id) order_number
from orders
order by id;
In MySQL 5.7 you could do this:
select customer_id,
(select count(*)
from orders
where customer_id = main.customer_id and id <= main.id)
from orders main;

Group By with Max Date and another column

I have the following table.
id
user_id
file_id
completed
updated
1
161
10
1
2022-10-11
2
164
11
1
2022-10-12
3
161
10
1
2022-10-12
4
167
10
1
2022-10-10
5
167
10
1
2022-10-11
6
167
10
1
2022-10-12
I want to select the row for each user having the max updated date for each file_id.
SELECT * FROM user_file
WHERE updated = (SELECT uf.updated FROM user_file uf GROUP BY uf.user_id,uf.file_id)
I have come up with this query but it returns an error "Subquery returns more than 1 row"
Maybe you want to check these out?
SQL select only rows with max value on a column
Retrieving the last record in each group - MySQL
Personally prefer the window function solution
SELECT a.*
FROM (SELECT id, user_id, file_id, ...
ROW_NUMBER() OVER (PARTITION BY file_id ORDER BY updated DESC) ranked_order
FROM user_file) a
WHERE a.ranked_order = 1

Select multiple tables with only unique users and ordered by latest id

I have 2 tables, first one is called members:
id name show
1 John 1
2 Wil 1
3 George 1
4 Chris 1
Second is called score:
id user_id score
1 1 90
2 1 70
3 2 55
4 3 30
5 3 40
6 3 100
7 4 30
user_id from score is the id of members.
What I want is to show a scorelist with unique members.id, ordered by score.score and order by the latest score.id.
I use the following code:
SELECT members.id, members.show, score.id, score.user_id, score.score FROM members
INNER JOIN score ON score.user_id = members.id
WHERE members.show = '1'
GROUP BY score.user_id
ORDER BY score.score DESC, score.id DESC
The output is not ordered by the latest score.id, but it does show only unique user_id's:
id user_id score
1 1 90
3 2 55
4 3 30
7 4 30
It should be like:
id user_id score
6 3 100
2 1 70
3 2 55
7 4 30
I hope you can help me
You could use:
with cte as (
select id,
user_id,
score,
row_number() over(partition by user_id order by id desc) as row_num
from score
) select cte.id,user_id,score
from cte
inner join members m on cte.user_id=m.id
where row_num=1
order by score desc;
Demo
If your MySQL server doesn't support windows function, use:
select s.id,s.user_id,s.score
from score s
inner join members m on s.user_id=m.id
where s.id in (select max(id) as id
from score
group by user_id
)
order by score desc;
Demo

SQL sum of maxes of each occurrence

I have the following table:
category id date views
1 3 5-1-17 40
1 3 5-2-17 70
1 3 5-3-17 110
1 3 5-4-17 200
1 5 5-1-17 50
1 5 5-2-17 75
2 6 4-1-17 90
2 6 4-2-17 95
2 9 4-3-17 115
2 9 6-5-17 125
2 9 6-6-17 135
How do I sum the max views for each id by category?
The resulting pull should look like this:
category views
1 275
2 230
For category 1, the max views for id 3 is 200 and the max views for id 5 is 75. The sum for category 1 is thus 275.
For category 2, the max views for id 6 is 95 and the max views for id 9 is 135. The sum for category 2 is thus 230.
You can use two levels of aggregation:
select category, sum(max_views)
from (select category, id, max(views) as max_views
from t
group by category, id
) t
group by category;
You can also use row_number() here:
select category, sum(max_views)
from (select t.*,
row_number() over (partition by category, id, order by views desc) as seqnum
from t
) t
where seqnum = 1
group by category;
It would be interesting which is faster. I would vote on the double aggregation, but that might not always be true.

MySQL Check if a value is within the range of values derived from a subquery

I need help with a query, I have a table ,here is an example
Item Code Qty Price Supplier
1234 1 20 A
1234 3 15 B
1234 6 2 C
4321 2 8 D
4321 7 1 A
4321 9 5 G
5432 8 10 E
5432 3 2 F
5467 5 9 H
5467 5 7 K
I have a subquery which contains distinct Item code, max(price) and 75%of max(price),this is the result.
Item Code Max value Min Value
1234 20 15
4321 8 6
5432 10 7.5
5467 9 6.75
and I need pull only those rows from first table if the price falls within the range of second table for the particular Item Code. Can anyone help?
You might give this a try:
SELECT
a.*
FROM items a
JOIN (
SELECT
item_code,
MAX(Price) as Max_Value,
MAX(Price) * 0.75 as Min_Value
FROM items
GROUP BY item_code) b
ON a.item_code = b.item_code
WHERE a.price between b.Min_Value AND b.Max_Value
order by a.item_code, a.price ASC
I will get first the max price per itemCode and join to the main table using itemCode and chwck that the price is between 75% of max and max price per item.
Select tbl.*
From myTable tbl
Join (
Select item_code,
max(price) as mx,
Round(max(price)*.75,0) as mx75
From myTable
Group by item_code) tab
On tbl.item_code = tab.item_code
And tbl.price between tab.mx75 and tab.mx
Order by 1, 4