Highest total salary - mysql

I have 3 tables with the following values and the question is : Find the name of the instructor with the highest total salary along with the names of the dancers he trains.
I was thinking something like :
Select Instructor.name, Dancer.name
FROM Instructor, Dancer, Info
WHERE Instructor.i_ID=Info.ints_id
AND Dancer.d_ID=Info.danc_id
GROUP BY Info.inst_id, Info.danc_id
ORDER BY SUM(Info.salary)
DESC LIMIT 2;
But the output is not right and also I am not suppose to know how many dancers every instructor has, so DESC LIMIT 2 is definitely wrong.

Join properly the tables and group by instructor to get the total salary for each.
Then sort descending by the total salary and keep only the 1st row.
With group_concat() you get the names of the dancers as a comma separated list:
select i.name,
sum(n.salary) total_salary,
group_concat(d.name) dancers
from instructor i
inner join info n on n.inst_id = i.i_id
inner join dancer d on d.danc_id = d.d_id
group by i.i_id, i.name
order by total_salary desc limit 1
Note that this query will return only 1 row, so if there are 2 instructors with the same top total salary you will get only 1.
If you want in the results ties in the top salary then use a HAVING clause:
select i.name,
sum(n.salary) total_salary,
group_concat(d.name) dancers
from instructor i
inner join info n on n.inst_id = i.i_id
inner join dancer d on d.danc_id = d.d_id
group by i.i_id, i.name
having total_salary = (select sum(salary) from info group by inst_id order by sum(salary) desc limit 1)

Try This:
select tab3.name "Instructor",tab2.name "Dancer"
from info tab1
inner join
dancer tab2 on tab1.dance_id=tab2.d_id
inner join
(select t1.inst_id,t2.name, sum(t1.salary) as "total_salary" from info t1
inner join instructor t2
on t1.inst_id=t2.i_id
group by t1.inst_id,t2.name
order by total_salary desc limit 1) tab3
on tab3.inst_id=tab1.inst_id
DB-FIDDLE

well it's a bit odd relation table but you could try something like this
SELECT
ins.name,
SUBSTRING_INDEX(GROUP_CONCAT(inf.salary ORDER BY inf.salary DESC),',',1) salary,
SUBSTRING_INDEX(GROUP_CONCAT(d.name ORDER BY inf.salary DESC),',',1) dancer_name
FROM Instructor ins
JOIN Info inf ON (ins.i_ID=inf.inst_id)
JOIN Dancer d on (d.d_ID=danc_id)
GROUP BY ins.i_ID
LIMIT 1;

Related

MySQL selecting names of customer with most purchase

I have 5 tables connected with each other in the image
[![Image1][1]][1]
I have tried writing query
SELECT lastname,firstname
FROM customer,purchase_order
where customer.customer_id=purchase_order.customer_id
What parameter should I consider for most purchase?
You can solve that by adjusting the select clause (remove order_id).
Then you will need a HAVING clause to implement the condition to only show the customers with the most purchase orders.
SELECT lastname,firstname
FROM customer
INNER JOIN purchase_order
ON customer.customer_id=purchase_order.customer_id
GROUP BY customer_id
ORDER BY COUNT(order_id) DESC LIMIT 1;
select lastname, firstname from customer c
inner join (
select customer_id, count(1) from purchase_order
group by 1
order by 2 desc limit 1) most
/* the above sub-query named as 'most' fetched the customer id with the maximum
number of orders */
on c.customer_id = most.customer_id; -- this is a simple join of customers table with the table generated from sub-query above
SELECT c.firstname,c.lastname
FROM customer c
JOIN purchase_order po
ON c.customer_id = po.customer_id
GROUP BY c.firstname,c.lastname
ORDER BY COUNT(po.order_id) DESC LIMIT 1;

Subquery not outputting the correct result?

I hope someone can help me with this problem, I been trying different combinations but can't seems to get the correct result.
First of all, I have 3 tables, category, department, and master, master has the FK. I want to get sum of total time for each department and sum of total time for category group by department so that I can see which department has how much time for that category, all should be group by department and in the correct order?
I can get the result but not coming out right, here is my code...
SELECT a.department, time_spent , COUNT(DISTINCT (a.department)), sum_quarantine FROM
(SELECT d.department, SUM(time_spent) as time_spent
FROM master as m
INNER JOIN department as d ON d.dept_id = m.dept_id GROUP BY d.department) AS a,
(SELECT d.department, c.category, SUM(time_spent) as sum_quarantine
FROM master as m
INNER JOIN category as c ON c.cat_id = m.cat_id
INNER JOIN department as d ON d.dept_id = m.dept_id
WHERE category = 'Quarantine' GROUP BY d.department) as b
GROUP BY b.department
What you want can be done without sub-query, making use of a CASE WHEN in a SUM, so that it only sums what you are interested in ('Quarantine'):
SELECT d.department,
SUM(CASE c.category
WHEN 'Quarantine' THEN time_spent
END) as sum_quarantine,
SUM(time_spent) time_spent,
COUNT(DISTINCT (c.category)) category_count
FROM master as m
INNER JOIN category as c ON c.cat_id = m.cat_id
INNER JOIN department as d ON d.dept_id = m.dept_id
GROUP BY d.department
ORDER BY 1
Here is fiddle.
Note that I added a count as well, since there was one in your attempt. But yours would always return 1, so I am not sure what you were looking for. I have added the number of categories linked to the department.
Also you did not specify the order you want, but it is easy to adapt the ORDER BY clause. The above query orders results by department, but if for instance you want to order by the second column in descending order, then do:
...
ORDER BY 2 DESC
If your results includes NULL values, and you prefer to have zeroes instead, then make use of the COALESCE function. For example:
COALESCE(SUM(time_spent), 0) time_spent,

Ordering JOIN results when grouping

Take the below for example:
SELECT
*
FROM
auctions AS a
LEFT JOIN winners AS w ON a.auction_id=w.auction_id
WHERE
a.active=1
AND
a.approved=1
GROUP BY
a.auction_id
ORDER BY
a.start_time DESC
LIMIT
0, 10;
Sometimes this may match multiple results in the winners table; I don't need both of them, however I want to have control over which row I get if there are multiple matches. How can I do an ORDER BY on the winners table so that I can make sure the row I want is the first one?
It is difficult to accurately answer without seeing your table structure but if your winners table has a winner date column or something similar, then you can use an aggregate function to get the first record.
Then you can return the record with that earliest date similar to this:
SELECT *
FROM auctions AS a
LEFT JOIN winners w1
ON a.auction_id=w1.auction_id
LEFT JOIN
(
select auction_id, min(winner_date) MinDate -- replace this with the date column in winners
from winners
group by auction_id
) AS w2
ON a.auction_id=w2.auction_id
and w1.winner_date = w2.MinDate
WHERE a.active=1
AND a.approved=1
ORDER BY a.start_time DESC
SELECT *
FROM auctions AS a
LEFT JOIN (select auction_id from winners order BY auction_id limit 1) AS w ON a.auction_id = w.auction_id
WHERE a.active = 1
AND a.approved = 1
GROUP BY a.auction_id
ORDER BY a.start_time DESC
Change the reference to the winners table in the join clause to a sub-query. This then gives you control over the number of records returned, and in what order.

MySQL Group BY, Having, Order By Query

Ok, so assume I have the following tables:
recipes
id (pk)
name
added
modified
recipe_versions
id (pk)
recipe_id (fk to recipes.id)
version
content
added
What I want is a query that grabs the latest recipe_versions.added data and then joins with the base recipe data. Then sorts all results by recipes.added ASC I have the following, but the group by, is not selecting the latest recipe_versions row, seems to be selecting the first.
SELECT r.`id`,
r.name,
rv.version,
rv.content,
r.added,
r.modified,
FROM recipes r,
recipe_versions rv
WHERE r.`id` = rv.recipe
GROUP BY rv.recipe
HAVING max(rv.added)
ORDER BY r.added ASC
Use this solution:
SELECT
c.*, b.*
FROM
(
SELECT recipe_id, MAX(added) AS mostrecent
FROM recipe_versions
GROUP BY recipe_id
) a
INNER JOIN
recipe_versions b ON
a.recipe_id = b.recipe_id AND
a.mostrecent = b.added
INNER JOIN
recipes c ON a.recipe_id = c.id
ORDER BY
c.added

How can I use MySQL to COUNT with a LEFT JOIN?

How can I use MySQL to count with a LEFT JOIN?
I have two tables, sometimes the Ratings table does not have ratings for a photo so I thought LEFT JOIN is needed but I also have a COUNT statement..
Photos
id name src
1 car bmw.jpg
2 bike baracuda.jpg
Loves (picid is foreign key with photos id)
id picid ratersip
4 1 81.0.0.0
6 1 84.0.0.0
7 2 81.0.0.0
Here the user can only rate one image with their IP.
I want to combine the two tables in order of the highest rating. New table
Combined
id name src picid
1 car bmw.jpg 1
2 bike baracuda.jpg 2
(bmw is highest rated)
My MySQL code:
SELECT * FROM photos
LEFT JOIN ON photos.id=loves.picid
ORDER BY COUNT (picid);
My PHP Code: (UPDATED AND ADDED - Working Example...)
$sqlcount = "SELECT p . *
FROM `pics` p
LEFT JOIN (
SELECT `loves`.`picid`, count( 1 ) AS piccount
FROM `loves`
GROUP BY `loves`.`picid`
)l ON p.`id` = l.`picid`
ORDER BY coalesce( l.piccount, 0 ) DESC";
$pics = mysql_query($sqlcount);
MySQL allows you to group by just the id column:
select
p.*
from
photos p
left join loves l on
p.id = l.picid
group by
p.id
order by
count(l.picid)
That being said, I know MySQL is really bad at group by, so you can try putting the loves count in a subquery in your join to optimize it:
select
p.*
from
photos p
left join (select picid, count(1) as piccount from loves group by picid) l on
p.id = l.picid
order by
coalesce(l.piccount, 0)
I don't have a MySQL instance to test out which is faster, so test them both.
You need to use subqueries:
SELECT id, name, src FROM (
SELECT photos.id, photos.name, photos.src, count(*) as the_count
FROM photos
LEFT JOIN ON photos.id=loves.picid
GROUP BY photos.id
) t
ORDER BY the_count
select
p.ID,
p.name,
p.src,
PreSum.LoveCount
from
Photos p
left join ( select L.picid,
count(*) as LoveCount
from
Loves L
group by
L.PicID ) PreSum
on p.id = PreSum.PicID
order by
PreSum.LoveCount DESC
I believe you just need to join the data and do a count(*) in your select. Make sure you specify which table you want to use for ambigous columns. Also, don't forget to use a group by function when you do a count(*). Here is an example query that I run on MS SQL.
Select CmsAgentInfo.LOGID, LOGNAME, hCmsAgent.SOURCEID, count(*) as COUNT from hCmsAgent
LEFT JOIN CmsAgentInfo on hCmsAgent.logid=CmsAgentInfo.logid
where SPLIT = '990'
GROUP BY CmsAgentInfo.LOGID, LOGNAME, hCmsAgent.SOURCEID
The example results form this will be something like this.
77615 SMITH, JANE 1 36
29422 DOE, JOHN 1 648
Hope that helps. Good Luck.