How to get the sum of a specific user from two tables? - mysql

I currently have 2 tables:
Favorite:
userID
drinkName
History:
userID
drinkName
I want to get the sum of the total times a specific userID shows up in each table, and then then the total number of times userID shows up in both tables.
(SELECT COUNT(userID) AS totalDrinks FROM History
WHERE userID = 'sai') union
(SELECT COUNT(userID) AS totalDrinks FROM Favorite
WHERE userID = 'sai')
So that code gets me the following output:
totalDrinks
4
2
However I am trying to use the MySQL sum function and that's not adding the two things up though.
So I was wondering how I would rewrite my query to output 6?

SELECT SUM(userID)as totalDrinks FROM History h
JOIN Favorite f ON h.userID=f.userID
GROUP BY userID
WHERE userID = 'sai'

Your UNION approach was almost there. You will have to SUM the result of both queries:
SELECT SUM(totalDrings) totalDrings FROM (
SELECT COUNT(*) totalDrinks FROM History
WHERE userID = 'sai'
UNION ALL
SELECT COUNT(*) FROM Favorite
WHERE userID = 'sai'
) s
A few things to note. You should use UNION ALL otherwise if the COUNTs result in the same number then they will be added only once. Another thing is that you should not use an INNER JOIN in here as that will force the users to be present in both tables.

Related

Using JOIN in sql for two derived tables

Basically, I have two separate queries, which I need to somehow merge into one set of results.
![This is Table 1, which shows the sum of each group's salary]
1
Here is the queries I wrote to form the tables.
SELECT con_stagename, SUM(p_daily_salary) AS sum_salary
FROM CONTENDER, PARTICIPANT
WHERE p_contender = con_id
GROUP BY con_id;
SELECT MAX(sum_salary) AS max_salary
FROM (SELECT con_stagename, SUM(p_daily_salary) AS sum_salary
FROM CONTENDER, PARTICIPANT
WHERE p_contender = con_id
GROUP BY con_id) T2;
And the question is, if I want the result to be a single row of values, which the name of the group with the highest salary, and the actual amount. How would I do it? I've been trying to use JOIN operations but there was not luck.
SELECT con_stagename, SUM(p_daily_salary) AS sum_salary
FROM CONTENDER, PARTICIPANT
WHERE p_contender = con_id
GROUP BY con_id
ORDER BY 2 DESC
LIMIT 1

Use SELECT through three table

I tried to write a query, but unfortunately I didn't succeed.
I want to know how many packages delivered over a given period by a person.
So I want to know how many packages were delivered by John (user_id = 1) between 01-02-18 and 28-02-18. John drives another car (another plate_id) every day.
(orders_drivers.user_id, plates.plate_name, orders.delivery_date, orders.package_amount)
I have 3 table:
orders with plate_id delivery_date package_amount
plates with plate_id plate_name
orders_drivers with plate_id plate_date user_id
I tried some solutions but didn't get the expected result. Thanks!
Try using JOINS as shown below:
SELECT SUM(o.package_amount)
FROM orders o INNER JOIN orders_drivers od
ON o.plate_id=od.plate_id
WHERE od.user_id=<the_user_id>;
See MySQL Join Made Easy for insight.
You can also use a subquery:
SELECT SUM(o.package_amount)
FROM orders o
WHERE EXISTS (SELECT 1
FROM orders_drivers od
WHERE user_id=<user_id> AND o.plate_id=od.plate_id);
SELECT sum(orders.package_amount) AS amount
FROM orders
LEFT JOIN plates ON orders.plate_id = orders_drivers.plate_id
LEFT JOIN orders_driver ON orders.plate_id = orders_drivers.plate_id
WHERE orders.delivery_date > date1 AND orders.delivery_date < date2 AND orders_driver.user_id = userid
GROUP BY orders_drivers.user_id
But seriously, you need to ask questions that makes more sense.
sum is a function to add all values that has been grouped by GROUP BY.
LEFT JOIN connects all tables by id = id. Any other join can do this in this case, as all ids are unique (at least I hope).
WHERE, where you give the dates and user.
And GROUP BY userid, so if there are more records of the same id, they are returned as one (and summed by their pack amount.)
With the AS, your result is returned under the name 'amount',
If you want the total of packageamount by user in a period, you can use this query:
UPDATE: add a where clause on user_id, to retrieve John related data
SELECT od.user_id
, p.plate_name
, SUM(o.package_amount) AS TotalPackageAmount
FROM orders_drivers od
JOIN plates p
ON o.plate_id = od.plate_id
JOIN orders o
ON o.plate_id = od.plate_id
WHERE o.delivery_date BETWEEN convert(datetime,01/02/2018,103) AND convert(datetime,28/02/2018,103)
AND od.user_id = 1
GROUP BY od.user_id
, p.plate_name
It groups rows on user_id and plate_name, filter a period of delivery_date(s) and then calculate the sum of packageamount for the group

Optimize MySQL query nested not exists possible?

I have list of submissions of exercises done by students who are part of a group(classroom), this contains:
submission table: userId, groupId, exercise_id (and more irrelevant data)
users table: userId, groupId
I want to select all the exercises done by all the students in a specific group. For this I currently have:
SELECT DISTINCT(exercise_id) FROM submissions as c1 WHERE c1.groupId = 1
AND NOT EXISTS(
SELECT DISTINCT(UserId) FROM users as u WHERE u.GroupId = 1
AND NOT EXISTS (
SELECT exercise_id FROM submissions as c2 WHERE u.UserId = c2.UserId
AND c2.exercise_id = c1.exercise_id
)
)
i.e. I select all the exercises for which there are no users in the group that have not done the exercise.
However, this query takes 5 seconds on a submission table with 1.5 million rows. Which steps could I take to further optimise this query? I have considered inner joins, but won't this result in the same query execution plan?
The groupid really shouldn't be in both tables. Assuming the values are consistent, try the following:
select s.exercise_id
from submissions s
where s.groupid = 1
group by s.exercise_id
having count(distinct userid) = (select count(distinct userid) from users where groupid = 1);
For performance, you want an index on submissions(groupid, exercise_id). Also, if you know there are no duplicate submissions or users, then remove the distinct, because that has an adverse effect on performance.

Select max with group by on other table

I have 2 tables: users_item that has 2 columns user_id, item_id and item_rates that has 2 columns rate_item_id, rate.
They are connected with Foreign_Key on users_item.item_id = item_rates.rate_item_id. I need to
select item_id's with max rate for a given range of users. One user can have a lot of items.
My select is:
SELECT MAX(rate), rate_item_id, user_id
FROM users_item JOIN item_rates ON item_id = rate_item_id
AND user_id in (2706,2979) GROUP BY user_id;
but it returns not correspondent item_id's with max rate. In given example select has to return just 2 rows. Can someone help on this. Thanks in advance.
Ok, I found what you want.. Try this:
SELECT users_item.user_id, item_id, maxrate
FROM user_items
JOIN item_rates ON users_item.item_id = item_rates.rate_item_id
JOIN (SELECT MAX(rate) AS maxrate, user_id
FROM users_item JOIN item_rates ON item_id = rate_item_id
WHERE user_id in (1,2)
GROUP BY user_id) AS maxis
ON users_item.USER_ID = maxis.USER_ID
WHERE item_rates.rate = maxrate
The reason you need a subquery is that multiple different items own by the same user could have the same rate and this could be the maximum rate of user's owned items.
Try grouping by user_id, rate_item_id
I'm surprised that MySql doesn't give you an error, Oracle would...

Combine search from 2 rows in mysql

I run a survey where all answers are stored in a separate row in the 'survey' table.
My table looks like this:
(ID,user_id,Q,A)
(1,10,'laundry','oxiclean')
(2,10,'laundry','tide')
(3,10,'laundry','pods')
(4,11,'laundry','spray n wash')
(5,11,'laundry','resolve')
(6,12,'laundry','oxiclean')
(7,13,'laundry','oxiclean')
I now need to pull the count of user id that selected ONLY specific products.
"SELECT *, count(user_id) FROM survey WHERE Q='laundry' GROUP BY a"
the above will give a an overall COUNT but I need to get my count based on users that selected ONLY 'oxiclean' for example. This should return 2.
Or users that selected 'oxiclean' AND 'tide' ONLY.
How do I go about performing this 'combination' of results pulled from different rows?
Thanks a lot!
select user_id from survey group by user_id having count(user_id) = 1
This retrieves a list of users which have only one answer in the survey. Use it as a filter condition:
select q,a,count(user_id)
from survey
where a = 'oxiclean'
and user_id in (select user_id from survey group by user_id having count(user_id) = 1)
You can achieve that using a subquery, for your case it will be something like that :
SELECT *, COUNT(user_id)
FROM survey AS s
WHERE Q = 'laundry'
AND A = 'oxiclean'
AND user_id NOT IN (SELECT user_id FROM survey WHERE Q = s.Q AND A != s.A);
s.Q and s.A refer to the parent field so you don't have to reinject the name a second time.
Downside : the query works only if you want one specific answer.
If you want one query to retrieve the overall count, this one should do the trick :
SELECT A, COUNT(user_id)
FROM (
SELECT A, user_id
FROM survey
WHERE Q='laundry'
GROUP BY user_id
HAVING COUNT(user_id) = 1
) AS t
GROUP BY A
Downside : the query give only answers who have only at least one unique user_id as seen here, and this syntax create a temporary table which is something to avoid for performance reasons.