Grouping in mysql with lower value from other column - mysql

Need group by on id and group and max of tval and lower of group if tval has duplicate/repeating values. Appreciate your help.
id
timel
group
tval
3
0
a
1.184
3
0.5
a
2.173
3
1
a
1.065
3
3
a
1.143
3
6
a
3.222
3
9
a
1.851
3
12
a
3.222
4
0
a
1.184
4
0.5
a
2.173
4
1
a
1.065
4
3
a
1.143
4
0.7
a
2.322
4
9
a
1.851
4
12
a
1.345
Expected output
id
group
timel
tval
3
a
6
3.222
4
a
0.7
2.322
Here is the create and inserts query for those who are interested to try it out.
CREATE TABLE sample (id INT, timel DOUBLE, group VARCHAR(50), tval DOUBLE);
INSERT INTO sample VALUES
(3,0,'a',1.184),
(3,0.5,'a',2.173),
(3,1,'a',1.065),
(3,3,'a',1.143),
(3,6,'a',3.222),
(3,9,'a',1.851),
(3,12,'a',3.222),
(4,0,'a',1.184),
(4,0.5,'a',2.173),
(4,1,'a',1.065),
(4,3,'a',1.143),
(4,0.7,'a',2.322),
(4,9,'a',1.851),
(4,12,'a',1.345);

Use NOT EXISTS to filter the table, so that you get only the rows with the max tval for each combination of id and group and then agregate to get the min timel:
SELECT s1.id, s1.trt, MIN(timel) timel, s1.tval
FROM sample s1
WHERE NOT EXISTS (
SELECT 1
FROM sample s2
WHERE s2.id = s1.id AND s2.trt = s1.trt AND s2.tval > s1.tval
)
GROUP BY s1.id, s1.trt, s1.tval
If your version of MySql is 8.0+ you can do it with ROW_NUMBER() window function:
SELECT id, trt, timel, tval
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY id, trt ORDER BY tval DESC, timel) rn
FROM sample
) t
WHERE rn = 1
See the demo.

Related

MYSQL dynamic query from rows to columns

I have a table
or_id
emp_id
cs
val
100
1
x
3.4
100
1
x
4.5
100
1
y
5
100
1
y
6
200
2
a
12
200
2
b
11
200
2
c
14
I want my output table like:
or_id
emp_id
CS1
CS2
CS3
100
1
x
y
200
2
a
b
c
I tried every possible code but nothing seems to work. I want dynamic code for this.
This query is working, but for larger dataset the execution time is lengthy, so I need an optimized code.
select distinct or_id,emp_id,
(select cs from (
select distinct cost_center from orl where emp_id=m.emp_id) a limit 1 offset 0 ) cs1,
(select cost_center from (
select distinct cost_center from orl where emp_id=m.emp_id) a limit 1 offset 1 ) cs2,
(select cost_center from (
select distinct cost_center from orl where emp_id=m.emp_id) a limit 1 offset 2 ) cs3
from orl m
For three CS columns, in MYSQL8
WITH
sorted AS
(
SELECT
or_id,
emp_id,
cs,
ROW_NUMBER() OVER (PARTITION BY or_id, emp_id ORDER BY cs) AS ordinal
FROM
your_table
GROUP BY
or_id,
emp_id,
cs
)
SELECT
or_id,
emp_id,
MAX(CASE WHEN ordinal = 1 THEN cs END) AS cs1,
MAX(CASE WHEN ordinal = 2 THEN cs END) AS cs2,
MAX(CASE WHEN ordinal = 3 THEN cs END) AS cs3
FROM
sorted
GROUP BY
or_id,
emp_id
Demo: https://dbfiddle.uk/2QNiXt6O

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

MySQL group by with max value

Hi I have this table.
id lat lng userId
1 12 23 1
2 45 34 2
3 42 34 3
4 33 34 1
5 36 79 2
6 53 98 2
7 23 90 3
8 23 67 1
Here we have three users. (user ids 1,2,3). I want to get lateset record (id column max value) of each user.
My excepted output is this
userId lat lng
1 23 67
2 53 98
3 23 90
This query will give me group by option
SELECT
*
FROM
covid.locations
GROUP BY userId;
But how do I combine this with MAX(id) function.
One way is to use the following:
SELECT
cl.*
FROM covid.locations cl
INNER JOIN (
SELECT
userid
, MAX( id ) mid
FROM covid.locations
GROUP BY
userId
) g ON cl.userid = g.userid
AND cl.id = cl.mid
Another is to use row_number() over()
SELECT
userId
, lat
, lng
FROM (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY userid ORDER BY id DESC) rn
FROM covid.locations
GROUP BY
userId
) d
WHERE rn = 1
Both will identify the "most recent" row in the source table based in the id column of that table. Note that the second query requires MySQL version 8+ as this is when row_number() became supported in that database. The first query should run in dbms supporting SQL.
This will do
SELECT
*
FROM
covid.locations
where id in (select max(t.id) from covid.locations t group by t.userId)
order by id desc;
An example of the above query can be found in this SQLFiddle

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

Select max(Data)

I have a table:
id cod_pr Date nr
-------------------------------
1 22 12.10.2012 2
2 25 12.10.2012 3
3 22 12.11.2012 5
4 25 12.11.2012 2
5 22 12.12.2012 4
6 23 12.10.2012 3
How kan I select only max Date from each cod_pr?
select cod_pr,MAX(Date) from Table
group by cod_pr
If you want all columns, you can use ROW_NUMBER in a CTE:
WITH CTE AS
(
SELECT id,cod_pr,Date,nr,
ROW_NUMBER() OVER (PARTITION BY cod_pr ORDER BY Date DESC) AS RN
FROM dbo.Table
)
SELECT id,cod_pr,Date,nr, FROM CTE WHERE RN = 1
Otherwise you can simply use GROUP BY
SELECT cod_pr, MAX(Date) AS MaxDate
FROM dbo.Table
GROUP BY cod_pr