Group by with union mysql select query - mysql

(SELECT COUNT(motorbike.`owner_id`) as count,owner.`name`,transport.`type` FROM transport,owner,motorbike WHERE transport.type='motobike'
AND owner.`owner_id`=motorbike.`owner_id`
AND transport.`type_id`=motorbike.`motorbike_id` GROUP BY motorbike.owner_id)
UNION ALL
(SELECT COUNT(car.`owner_id`) as count,owner.`name`,transport.`type` FROM transport,owner,car WHERE transport.type='car'
AND owner.`owner_id`=car.`owner_id`
AND transport.`type_id`=car.`car_id` GROUP BY car.`owner_id`)
The query above returns a result like this below,
count name
1 Linda
2 Mary
1 Steve
1 Linda
This query is to count how many transport that owned by an owner. Linda have one car and one motorcycle,so the result should:
count name
2 Linda
2 Mary
1 Steve
I have tried this query,but return error:
(SELECT COUNT(motorbike.`owner_id`),owner.`name`,transport.`type` FROM transport,owner,motorbike WHERE transport.type='motobike'
AND owner.`owner_id`=motorbike.`owner_id`
AND transport.`type_id`=motorbike.`motorbike_id`)
UNION ALL
(SELECT COUNT(car.`owner_id`),owner.`name`,transport.`type` FROM transport,owner,car WHERE transport.type='car'
AND owner.`owner_id`=car.`owner_id`
AND transport.`type_id`=car.`car_id`) GROUP BY motorbike.owner_id
Can anyone help me please?

select sum(qty), name
from (
select count(m.owner_id) as qty, o.name
from transport t,owner o,motorbike m
where t.type='motobike' and o.owner_id=m.owner_id
and t.type_id=m.motorbike_id
group by m.owner_id
union all
select count(c.owner_id) as qty, o.name,
from transport t,owner o,car c
where t.type='car' and o.owner_id=c.owner_id and t.type_id=c.car_id
group by c.owner_id
) t
group by name

This may be what your after:
SELECT Count(Owner_ID), Name
FROM (
SELECT M.Owner_ID, O.Name, T.Type
FROM Transport As T, Owner As O, Motorbike As M
WHERE T.Type = 'Motorbike'
AND O.Owner_ID = M.Owner_ID
AND T.Type_ID = M.Motorbike_ID
UNION ALL
SELECT C.Owner_ID, O.Name, T.Type
FROM Transport As T, Owner As O, Car As C
WHERE T.Type = 'Car'
AND O.Owner_ID = C.Owner_ID
AND T.Type_ID = C.Car_ID
)
GROUP BY Owner_ID

Try this EDITED:
(SELECT COUNT(motorbike.owner_id),owner.name,transport.type FROM transport,owner,motorbike WHERE transport.type='motobike' AND owner.owner_id=motorbike.owner_id AND transport.type_id=motorbike.motorbike_id GROUP BY motorbike.owner_id)
UNION ALL
(SELECT COUNT(car.owner_id),owner.name,transport.type FROM transport,owner,car WHERE transport.type='car' AND owner.owner_id=car.owner_id AND transport.type_id=car.car_id GROUP BY car.owner_id)

Related

Displaying supervisors who supervised 3 or more employees

Employee TABLE
ID Name Supervisor_ID
1 James NULL
2 Peter 1
3 Howard 1
4 Michele 2
5 Nicholas 2
6 Donald 2
7 Jackson 3
8 Anderson 3
9 Jeff 3
10 Will 3
I should get this at the end
ID Name Supervisor_Of_X_Employee
4 Peter 3
2 Howard 4
I tried doing
SELECT t1.employee_id
FROM employee t1
JOIN (SELECT DISTINCT supervisor_id FROM employee) t2
ON t1.employee_id = t2.supervisor_id;
Doesn't seem to produce what I want
Any ideas?
Thanks
You want to find the supervisor count so you group on the supervisor id like this
SELECT Supervisor_ID, count(*) as CNT
FROM employee
GROUP BY Supervisor_ID
add a HAVING COUNT(*) > 2 to get the ones that are 3 or more.
Oh... but you want the name too? then you have to join back to the table to get the name.
SELECT E.ID, E.Name, SUB.CNT
FROM (
SELECT Supervisor_ID, count(*) as CNT
FROM employee
GROUP BY Supervisor_ID
HAVING COUNT(*) > 2
) AS SUB
JOIN employee as E on E.ID = SUB.Supervisor_ID
SELECT Supervisor_id, COUNT(*) AS Supervisor_Of_X_Employee
FROM employee
GROUP BY Supervisor_id
if you need the name you'll have to do an inner join
SELECT employee_grouped.Supervisor_id, employee.Name, Supervisor_Of_X_Employee
FROM employee
INNER JOIN (
SELECT Supervisor_id, COUNT(*) AS Supervisor_Of_X_Employee
FROM employee
GROUP BY Supervisor_id
) employee_grouped ON employee.Id = employee_grouped.Supervisor_id
I would suggest using a self join approach with aggregation here:
SELECT
e1.Name,
COUNT(*) AS Supervisor_Of_X_Employee
FROM employee e1
INNER JOIN employee e2
ON e1.ID = e2.Supervisor_ID
GROUP BY
e1.Name
HAVING
COUNT(*) > 2;
Demo

Getting data form 2 tables and summing values of the result

I have 2 tables with information: ID, persona_id, total_amount
The persona ID can repeat dozen of times. So i get all the one persons id total_amount with query:
select d.id as debt_id, p.name as persona, sum(d.total_amount) as total_amount
from debt d
join persons p on d.persona_id = p.id group by p.name
I want to get data from each table in one query and do aritmethic propertys with the total_amount column and return it as 1 tabel.
TABLE 1
id persons_id total_amount
1 2 50
2 3 100
3 2 200
4 5 300
5 1 500
TABLE 2
id persons_id total_amount
1 2 25
2 1 100
3 5 50
4 3 100
5 4 300
As a result i want to get the 2 tables comined with arithmetic operation (-, +, / , * ) of Total amount columns.Basicaly a change to get the ending result total amount in form i want for different cases.
What worked for me based on JohnHC answear was :
select c.id, c.persona_id, c.total_amount - d.total_amount as new_total
from ( select c.id , c.persona_id, sum(c.total_amount) as total_amount from credit c
join persons p on c.persona_id = p.id
group by p.name) c
inner join ( select d.id, d.persona_id, sum(d.total_amount) as total_amount from debt d
join persons p on d.persona_id = p.id
group by p.name) d
on c.persona_id = d.persona_id
group by c.id, c.persona_id
If you want the total, try:
select id, person_id, sum(total_amount)
from
(
select id, person_id, total_amount
from table1
union all
select id, person_id, total_amount
from table2
)
group by id, person_id
If you want to do other things, try:
select t1.id, t1.person_id, t1.total_amount [+ - / *] t2.total_amount as new_total
from table1 t1
inner join table2 t2
on t1.id = t2.person_id
group by t1.id, t1.person_id

SELECT COUNT() GROUP BY Set of data in IN() mysql

My table is like
Loves table (loves)
animal_id | user_id | time
1 1
2 1
1 3
1 5
2 3
3 1
Animals table(animal)
id | type | name
1 air animal 1
2 ground animal 2
3 water animal 3
4 space animal 4
5 air animal 5
6 ground animal 6
My Query
( select count(*) from loves where animal_id = a.animal_id) as n_l,
a.name
FROM animal a ,loves lp
WHERE a.animal_id = lp.animal_id
AND lp.user_id = $MYUSERID
AND a.type IN ($MYANIMALTYPES)
ORDER BY lp.time DESC
LIMIT 5
Now if $MYUSERID = 1 and $MYANIMALTYPES = 'air','ground'
I should get output as from above example
n_l | name
3 animal 1
2 animal 2
But for some reason i want to get combinations of
$MYANIMALTYPES = 'air','ground' ,
$MYANIMALTYPES = 'air','water' ,
$MYANIMALTYPES = 'space',
and
$MYANIMALTYPES = 'space','water
seperately in groups i have to run the above query 4 times for each $MYANIMALTYPES.
My problem is that I'm using too many queries for what i want. Is there any way to get what i want in One single query ?
UPDATE
For a simple understanding how do i combine these two queries below into one query ?
( select count(*) from loves where animal_id = a.animal_id) as n_l,
a.name
FROM animal a ,loves lp
WHERE a.animal_id = lp.animal_id
AND lp.user_id = $MYUSERID
AND a.type IN ('ground','air')
ORDER BY lp.time DESC
LIMIT 5
AND
( select count(*) from loves where animal_id = a.animal_id) as n_l,
a.name
FROM animal a ,loves lp
WHERE a.animal_id = lp.animal_id
AND lp.user_id = $MYUSERID
AND a.type IN IN ('air','space')
ORDER BY lp.time DESC
LIMIT 5
You could use this adaptation of your query. It adds a join to the 4 type combinations you are interested in:
SELECT ( SELECT count(*)
FROM loves
WHERE animal_id = a.animal_id) as n_l,
a.name,
trim(concat(types.type1, ' ', types.type2)) grp
FROM animal a
INNER JOIN loves lp
ON a.animal_id = lp.animal_id
INNER JOIN ( SELECT 'air' type1, 'ground' type2
UNION ALL
SELECT 'air', 'water'
UNION ALL
SELECT 'space', ''
UNION ALL
SELECT 'space', 'water' ) AS types
ON a.type IN (types.type1, types.type2)
WHERE lp.user_id = $MYUSERID
GROUP BY a.name,
trim(concat(types.type1, ' ', types.type2))
ORDER BY 3, lp.time DESC
LIMIT 15
I also set the limit higher as you will now get all the results in one query.
Here is a fiddle.
The problem is you cant use string directly
if you string is
$MYANIMALTYPES = "'air','ground'"
That translate into
a.type IN ('air,ground');
and you need
a.type IN ('air', 'ground');
Try with FIND_IN_SET
WHERE FIND_IN_SET(a.type, #MYANIMALTYPES) > 0

Mysql Join to show all records with or without matching records

I have two tables. One for employees and another for ratings. Some employees have been rated others not. I'm trying to list all the employees with or without a rating value and sort them from the highest rating.
emp table
empid empName
--------------
1 John
2 Alex
3 Peter
4 Mary
Ratings table
ratingid | customerid | ratingvalue | empid
---------------------------------------------
1 1 4 1
2 6 2 1
3 4 3 3
4 5 5 4
Expected output:
empid | empName | avgrating | ratingcount
---------------------------------------------
1 John 3 2
2 Alex 0 0
3 Peter 3 1
4 Mary 5 1
I tried
SELECT *, round(AVG(ratingvalue ), 2) as avgrating, count(empid) as ratingcount
FROM emp LEFT JOIN ratings ON emp.empid = ratings.empid ORDER BY `avgrating`
DESC
That query doesn't produce the result I expect. It only gives me one row.
Thanks in advance
need group by and coalesce null values to 0.
SELECT EmpID, empName,
coalesce(round(AVG(ratingvalue ), 2),0) as avgrating,
coalesce(count(empid),0) as ratingcount
FROM emp
LEFT JOIN ratings
ON emp.empid = ratings.empid
GROUP BY EmpID, EmpName
ORDER BY `avgrating`DESC
I think this is what you want.
select
e.id, e.name,
avg(coalesce(t1.rating,0)) average_rating,
count(coalesce(t1.rating,0)) count_rating
from
(select '1' id, 'John' name union all
select '2' id, 'Alex' name union all
select '3' id, 'Peter' name union all
select '4' id, 'Mary' name) e
left join (select '1' id, '1' customer_id, '4' rating, '1' emp_id union all
select '2' id, '6' customer_id, '2' rating, '1' emp_id union all
select '3' id, '4' customer_id, '3' rating, '3' emp_id union all
select '4' id, '5' customer_id, '5' rating, '4' emp_id) t1 on
t1.emp_id = e.id
group by
e.id,
e.name
I have just subbed out your tables for data. You can run this in mysql directly and it should give you want you want.

MySQL - how to reorder records depending on counted quantity

Please help me to figure out how to get table like this:
ID Name City
-- ---- ----
1 A 2
2 C 1
3 E 3
4 B 2
5 D 2
6 G 3
7 F 2
... to be sorted like this:
ID Name City
-- ---- ----
1 A 2
4 B 2
5 D 2
7 F 2
3 E 3
6 G 3
2 C 1
in other words I'd like it to be reordered depending on quantity of Names in a City firstly, and by Name secondly.
Cities having more Names should go first.
This should do the trick:
select c.* from c
inner join (
select City, count(*) as cnt from c group by City
) a
on c.City = a.City
order by a.cnt desc, c.name asc
Here is SQL Fiddle
SELECT ID,NAME,CITY,(select count(*) from AS T2 where T2.CITY = T1.CITY) as CITYCOUNT FROM AS T1 order by CITYCOUNT DESC,NAME ;
OR
SELECT ID,NAME,CITY FROM AS T1 order by (select count(*) from AS T2 where T2.CITY = T1.CITY)DESC,NAME ;
Alternatively you can also do this:
ALTER TABLE ADD COLUMN CITYCOUNT INT(11) DEFAULT 0;
UPDATE T1 (select CITY,count(*) as CITYCOUNT from group by CITY) T2 SET T1.CITYCOUNT = T2.CITYCOUNT where T1.CITY = T2.CITY;
SELECT ID,NAME,CITY,CITYCOUNT FROM AS T1 order by CITYCOUNT DESC,NAME
I think your example is not correct, Cities with Value 3 should come on Top, for this you can try this query:
SELECT
ID, Name, City
FROM <TABLE>
ORDER BY City DESC, Name ASC;
Hope this is what you want.
Updated Answer:
SELECT
Id, Name, T.City
FROM <TABLE> T
INNER JOIN
(SELECT DISTINCT
City, Count(City) AS CITYCOUNT
FROM Table_7
GROUP BY City) TEMP ON TEMP.City = T.City
ORDER BY TEMP.CITYCOUNT DESC