Filter twice with MAX() in MySQL - mysql

I have the following table called my_values in a MySQL 5.7 database:
value1
value2
value3
foo
7
something4
foo
5
something1
foo
12
anything5
bar
3
something7
bar
18
anything5
bar
0
anything8
baz
99
anything9
baz
100
something0
As you see, there are duplicates in value1. I want to SELECT each unique value1 only once, but that row with the highest value in value2.
I'm using this query for that:
SELECT v.* FROM my_values v WHERE v.value2 = (SELECT MAX(v2.value2) FROM my_values v2 WHERE v2.value1 = v.value1);
The result is:
value1
value2
value3
foo
12
anything5
bar
18
anything5
baz
100
something0
Here's a fiddle of that.
From this result I want to SELECT each unique value3 only once, but that row with the highest value in value2 (no matter what value1 is).
So expected result would be:
value1
value2
value3
bar
18
anything5
baz
100
something0
How can I do that?

here is how you can do it :
select t1.*
from my_values t1
natural join (select value1, MAX(value2) value2
from my_values
group by value1 ) t2
natural join (select value3, MAX(value2) value2
from my_values
group by value3) t3
fiddle

You can use tuples for the comparison:
select t.*
from my_values t
where (t.value2, t.value3) = (select t2.value2, t2.value3
from my_values t2
where t2.value1 = t.value1
order by t2.value2 desc, t2.value3 desc
limit 1
);

Related

CTE passing multiple subqueries

This is an extension to my previous post.
WITH cte1 AS (
SELECT * FROM Combination
WHERE Col1 = 'val' and city='karim'),
cte2 AS (
SELECT * FROM Combination
WHERE Col1 = 'val2' and city='karim')
SELECT CONCAT(cte1.Col2, cte2.Col2) AS Result
FROM cte1 CROSS JOIN cte2;
col1
col2
City
Val
145
Telang
val2
13
Telang
val2
25
Telang
val
146
karim
val2
124
karim
val2
56
karim
Output:
Result
14513
14525
146124
14656
There are multiple cities.I wanted to get combinations only for the values existing in the cities
Tried something like this, but does not work.
SELECT * FROM Combination
WHERE Column1 = 'value' and city IN(select city from Combinations);
Use an INNER self join of the table:
SELECT CONCAT(c1.Col2, c2.Col2) AS Result
FROM Combination c1 INNER JOIN Combination c2
ON c2.city = c1.city
WHERE c1.Col1 = 'val' AND c2.Col1 = 'val2';

SQL : Summing the values in a column till first non zero values appears in other column?

Suppose, I have a table t1 looking like
id
value1
value2
wk_id
1
2
0
1
1
1
1
2
1
3
0
3
2
2
1
2
2
2
0
3
3
1
0
2
3
2
0
4
3
3
0
5
And I want to sum up the value1 till non-zero value appears on the value2 for first time.
End product must look like this:
id
value1
1
2
2
0
3
6
How to perform this in SQL?
If your MySQL version support window function you can try to use SUM window function with condition aggregate function be a flag to represent your logic (till non-zero value appears on the value2 for first time)
Then do condition aggregate function again.
Query #1
SELECT id,
SUM(CASE WHEN flag = 0 THEN value1 ELSE 0 END) value1
FROM (
SELECT *,
SUM(CASE WHEN value2 = 1 THEN -1 ELSE 0 END) OVER(PARTITION BY ID ORDER BY wk_id) flag
FROM T
) t1
GROUP BY id;
id
value1
1
2
2
0
3
6
View on DB Fiddle
WITH cte AS (
SELECT *,
CASE WHEN SUM(value2) OVER (partition by id ORDER BY wk_id) = 0
THEN SUM(value1) OVER (partition by id ORDER BY wk_id)
ELSE 0
END sum_value1
FROM test
ORDER BY id, wk_id
)
SELECT id, MAX(sum_value1) sum_value1
FROM cte
GROUP BY id;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0fcdca008e4a821f952de4d608434bcf
One option is a NOT EXISTS clause, looking for the stop row (the first row with value2 = 1).
select id, sum(value1)
from mytable
where not exists
(
select null
from mytable stoprow
where stoprow.id = mytable.id
and stoprow.wk_id <= mytable.wk_id
and stoprow.value2 = 1
)
group by id
order by id;
Aggregating on a calculated rolling total of value2 can also be done via a self-join.
select id
, sum(if(roll_tot_value2=0,value1,0)) as total
from
(
select t1a.id, t1a.wk_id, t1a.value1
, sum(t1b.value2) as roll_tot_value2
from t1 as t1a
join t1 as t1b
on t1b.id = t1a.id
and t1b.wk_id <= t1a.wk_id
group by t1a.id, t1a.wk_id, t1a.value1
) q
group by id;
id
total
1
2
2
0
3
6
Test on db<>fiddle here
You can use a subquery:
select t.id, coalesce(
(select sum(t2.value1) from t1 t2 where t2.value2 = 0 and t2.id = t.id
and (not exists (select 1 from t1 t3 where t3.value2 = 1 and t3.id = t.id)
or t2.wk_id < (select min(t4.wk_id) from t1 t4 where t4.id = t.id and t4.value2 = 1))), 0)
from t1 t group by t.id

GROUP BY value1 and select row with highest of value2 within the group [duplicate]

This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed 1 year ago.
I have the following table called values in a MySQL 5.7 database:
value1
value2
value3
foo
7
something4
foo
5
something1
foo
12
anything3
bar
3
something7
bar
18
anything5
bar
0
anything8
baz
99
anything9
baz
100
something0
I want to GROUP BY value1 and always keep the row with the highest value in value2.
So the expected result of the table above is:
value1
value2
value3
foo
12
anything3
bar
18
anything5
baz
100
something0
How can I do that with SQL?
Schema and insert statements:
create table mytable (value1 varchar(50), value2 int, value3 varchar(50));
insert into mytable values('foo', 7, 'something4');
insert into mytable values('foo', 5, 'something1');
insert into mytable values('foo', 12, 'anything3');
insert into mytable values('bar', 3, 'something7');
insert into mytable values('bar', 18, 'anything5');
insert into mytable values('bar', 12, 'anything8');
insert into mytable values('baz', 99, 'anything9');
insert into mytable values('baz', 100, 'something0');
Query#1 (using inner join)
select m.* from mytable m inner join
(select value1, max(value2) maxvalue2 from mytable group by value1) m2
on m.value1=m2.value1 and m.value2=m2.maxvalue2
Output:
value1
value2
value3
foo
12
anything3
bar
18
anything5
baz
100
something0
Query#2 (using subquery in where clause)
select m.*
from mytable m
where m.value2 = (select max(m2.value2) from mytable m2 where m2.value1 = m.value1);
Output:
value1
value2
value3
foo
12
anything3
bar
18
anything5
baz
100
something0
db<fiddle here
You don't want to group. You want to filter! You are keeping the original rows.
One method uses a correlated subquery:
select v.*
from values v
where v.value2 = (select max(v2.value2)
from values v2
where v2.value1 = v.value1
);

Selecting distinct 5 columns combination in mysql

I have a mysql table that looks like this: Col 1 is UNIQUE.
1 value1 value2 0 2
2 value1 value2 1 3
3 value3 value4 3 2
4 value4 value5 4 1
5 value3 value4 3 1
I need a query to select all the rows with distinct column 1 and 2, for example the output I want for this example will look like this:
1 value1 value2 0 2
3 value3 value4 3 2
4 value4 value5 4 1
I need distinct col 1 and 2 but altogether all columns combination will be distinct always. I want to display distinct col 1,2 and 3 without col 2,3 repeating.
I've found a few samples on how to do it but they all select distinct on each column individually. I tried many stackoverflow answers too. But my question is different.
One method that performs well is a correlate subquery:
select t.*
from t
where t.col1 = (select min(t2.col1)
from t t2
where t2.col2 = t.col2 and t2.col3 = t.col3
);
For best performance, you want an index on (col2, col3, col1).
I strongly advise having a primary key on all tables, but if you did not have one, then row_number() would be the way to go:
select t.*
from (select t.*,
row_number() over (partition by col2, col3 order by col2) as seqnum
from t
) t
where seqnum = 1;
This incurs a tad more overhead because row numbers need to be assigned to all rows before they are filtered for only first one.
It could be achieved by using ROW_NUMBER:
SELECT *
FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY col2, col3 ORDER BY col1) AS rn
FROM tab) sub
WHERE rn=1

How to check for each same value we have same unique id in Mysql

I have a query with 3 left join gives me below mentioned output:
T2 ID value1 Type value2 frq Value3
L-1 AB-12 ARTY55A X [Null] 8 ARTY55A
L-1 AB-12 ARTy55A X [Null] 7 BHyT78B
L-2 AB-21 VGTY25E Y VGTY25E 8 VGTY25E
L-3 AB-14 [Null] Z FRTE20E 8 FRTE20E
L-5 AB-18 AURT10E X [Null] 8 AURT10E
L-5 AB-18 AURT10E X [Null] 7 AERT10E
L-6 AB-18 AURT10E X [Null] 8 AURT10E
Now i want to check count that for same Value3 with Type=X having frq 8, have the same unique ID with Distinct count 1.
And for all the same Value2 with Type!=X have the same unique ID with Distinct count 1. (Here we don't check frq)
Expected Result:
Value3 Value3_count ID_count Value2 Value2_count ID
ARTY55A 1 1 VGTY25E 1 1
AURT10E 2 1 [Null] [Null] [Null]
you could use a group by and count
select t.Value3, count(*)
from ( select a.Value3 from table1 left join..... ) t
where Type = 'X'
and frq = 8
group by t.Value3
and
select t.Value2, count(*)
from ( select a.Value3 from table1 left join..... ) t
where Type != 'X'
group by t.Value2
You can try this:
select Value3, count(*) as Value3_count, count(distinct ID) as ID_count
from ( my query with 3 left join ) t
where Type = 'X' and frq = 8
group by Value3;
select Value2, count(*) as Value2_count, count(distinct ID) as ID_count
from ( my query with 3 left join ) t
where Type != 'X'
group by Value2;