MySQL query with GROUP BY, SUM, MAX and subquery - mysql

I have the following tabel structure:
Id Num1 Num2 Type Num3
1 2 2 1 4
1 3 1 2 5
1 1 1 3 2
2 2 1 1 3
2 0 1 2 2
2 4 3 3 6
I need a query with group by 'Id', sum of 'Num1', sum of 'Num2', max of 'Num3' and the 'Type' related to the MAX of 'Num3'.
So, the desired output is:
Id Sum(Num1) Sum(Num2) type Max(Num3)
1 6 4 2 5
2 6 4 3 6
Without this related 'Type' the query below works fine:
SELECT
Id,
SUM(Num1),
SUM(Num2),
MAX(Num3)
GROUP BY
Id
I tried different methods of subquery but can't make it work yet.

Your problem is a bit of a spin on the greatest value per group problem. In this case, we can use a subquery to find the max Num3 value for each Id. But, in the same subquery we also compute the sum aggregates.
SELECT
t1.Id,
t2.s1,
t2.s2,
t1.Type,
t1.Num3
FROM yourTable t1
INNER JOIN
(
SELECT Id, SUM(Num1) AS s1, SUM(Num2) AS s2, MAX(Num3) AS m3
FROM yourTable
GROUP BY Id
) t2
ON t1.Id = t2.Id AND t1.Num3 = t2.m3;
As a hat tip to MySQL 8+, and to ward off evil spirits, we can also write a query using analytic functions:
SELECT Id, s1, s2, Type, Num3
FROM
(
SELECT
Id,
SUM(Num1) OVER (PARTITION BY Id) s1,
SUM(Num2) OVER (PARTITION BY Id) s2,
Type,
Num3,
MAX(Num3) OVER (PARTITION BY Id) m3
FROM yourTable
) t
WHERE Num3 = m3;

Related

Get row has Max value in MySQL?

I want to get staff_id = AZ has MAX(step) value of this table (name: test).
id
general_id
staff_id
step
1
4
A1
1
2
4
AZ
2
3
4
A2
3
4
5
A3
1
5
5
A4
2
6
5
AZ
3
SELECT MAX(step) AS STEP, staff_id
FROM test AS t
WHERE staff_id = AZ
GROUP BY general_id
For just one staff, you can use order by and limit:
select *
from test
where staff_id = 'AZ'
order by step desc limit 1
If you want to do this for multiple staffs at once, then one option uses a correlated subquery:
select *
from test t
where t.step = (select max(t1.step) from test t1 where t1.staff_id = t.staff_id)
Another feature of this approach is that it allows top ties, if any.
Or, in MySQL 8.0, you can use window functions:
select *
from (
select t.*,
rank() over(partition by staff_id order by step desc) rn
from test t
) t
where rn = 1

Get Duplicated Count Without Removing

I am trying to get duplicate counts but without actually removing duplicates.
I tried using GROUP BY id and then COUNT(id) but it removes all duplicate entries.
Is there any way to not remove duplicates?
The table looks like this:
ID1 ID2 Value
1 2 someval
1 3 someval
1 4 someval
2 3 someval
2 1 someval
3 1 someval
4 1 someval
I am trying to get this:
ID1 ID2 Value COUNT
1 2 someval 3
1 3 someval 3
1 4 someval 3
2 3 someval 2
2 1 someval 2
3 1 someval 1
4 1 someval 1
I used this:
SELECT ID1, ID2, Value, COUNT(ID1) FROM table GROUP BY ID1;
One of way doing this is to have a separate query for the count and join on it:
SELECT t.id1, t.id2, t.value, cnt
FROM my_table t
JOIN (SELECT id1, count(*) AS cnt
FROM my_table
GROUP BY id1) c ON t.id1 = c.id1
You can do this with a correlated subquery in MySQL;
select id1, id2, value,
(select count(*) from table t2 where t2.id1 = t.id1) as count
from table t;
If performance is an issue then an uncorrelated subquery will likely be orders of magnitude faster than a correlated one...
SELECT x.*
, cnt
FROM my_table x
JOIN
( SELECT id1,COUNT(*) cnt FROM my_table GROUP BY id1) y
ON y.id1 = x.id1;
try something like this :
SELECT YourColumn, COUNT(*) TotalCount
FROM YourTable
GROUP BY YourColumn
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC

Find duplicate records in MySQL without named column

I have a table like this:
**lead_id** **form_id** **field_number** **value**
1 2 1 Richard
1 2 2 Garriot
2 2 1 Hellen
2 2 2 Garriot
3 2 1 Richard
3 2 2 Douglas
4 2 1 Tomas
4 2 2 Anderson
Where field_number = 1 is the name and field_number = 2 is the surname.
I would like to find entries that are equal by name OR surname and group them by lead_id, so the output could be like this:
1
2
3
Any thoughts on how this can be done?
This should work and be reasonably efficient (depending upon indexes):
select distinct lead_id
from tablename as t1
where exists (
select 1
from tablename as t2
where t1.field_number = t2.field_number
and t1.value = t2.value
and t1.lead_id <> t2.lead_id
)
Select leadid from (
Select DISTINCT leadid,value from tablename
Where fieldnumber=1
Group by leadid,value
Having count(value) >1
Union all
Select DISTINCT leadid,value from tablename
Where fieldnumber=2
Group by leadid,value
Having count(value) >1
) as temp
Surely there is a faster option

How to group repeated row values in a column

t_no name value
1 a 45
1 b 23
1 c 5
1 a 12
1 b 99
1 c 6
I need to show my above table as
no name value1 value2
1 a 45 12
1 b 23 99
1 c 5 6
You can't create dynamic columns in mysql alone, either in scripting language, or you can use group_concat to have them in one column:
SELECT to_no, name, GROUP_CONCAT(value)
FROM table GROUP BY to_no, name
result:
no name value
1 a 45,12
1 b 23,99
1 c 5,6
MySQL does not have a pivot function, but you can use an aggregate function with a CASE expression. Since you have multiple values for each t_no and name, then you could use user defined variables to assign a row number to each group of values:
select t_no, name,
max(case when rn=1 then value end) value1,
max(case when rn=2 then value end) value2
from
(
select t_no, name, value,
#rn:=case when #prev=t_no and #c=name then #rn else 0 end +1 rn,
#prev:=t_no,
#c:=name
from yourtable
cross join (select #rn:=0, #prev:=0, #c:=null) c
order by t_no, name
) d
group by t_no, name
order by t_no, name;
See SQL Fiddle with Demo

most frequent observation or median of a set

I am aggregating data and I cannot sum certain columns so I would like to take the most frequent observation from that column, or the median value. Example follows, thanks in advance.
ID site
1 3
1 3
1 2
1 3
2 4
2 5
2 5
2 5
I want it to look like
ID Site
1 3
2 5
WITH temp AS(
SELECT ID, Site, COUNT(*) As counts
FROM id_table
GROUP BY ID, Site
)
SELECT temp.ID, temp.Site
FROM temp
JOIN (SELECT ID, MAX(counts) max_counts
FROM temp
GROUP BY ID
)b
ON temp.ID = b.ID
AND temp.counts = b.max_counts
ORDER BY ID ASC
SQL Fiddle