how to count winner for this table using join query - mysql

candidate table
---------------------------
Id Name
1 James
2 peter
3 robin
4 max
vote table
-----------------------
vote candidate id
1 1
1 1
1 1
1 2
1 3
1 3
1 2
how to count winner in mysql ....by this data base

Suppose if there are two persons with same votes then there will be two winners for this situation you can do so
SELECT c.*,
COUNT(*) `votes`,
t.votes_total
FROM candidate c
LEFT JOIN vote v ON(v.candidate_id = c.id)
JOIN (SELECT COUNT(*) votes_total FROM vote
GROUP BY candidate_id
ORDER BY votes_total DESC
LIMIT 1) t
GROUP BY c.id
HAVING votes=t.votes_total
ORDER BY votes DESC
Other wise if you don't care for morethan one winners then you can use the ORDER BY with LIMIT technique provided by Abhik Chakraborty
Fiddle demo

select
c.name,
sum(v.vote) as total_votes
from candidate c
inner join vote v on v.candidate_id = c.Id
group by c.Id
order by total_votes desc limit 1
This will give the winner.
If you want to list all of them in order i.e. top to bottom use as
select
c.name,
sum(v.vote) as total_votes
from candidate c
inner join vote v on v.candidate_id = c.Id
group by c.Id
order by total_votes desc

Related

Why the join is not working without group by statement

If I remove the group by statement, then it is showing an error.
SELECT COMPANY.COMPANY_CODE,
company.founder,
count(distinct lm.lead_manager_code),
count(distinct sm.senior_manager_code),
count(distinct m.manager_code),
count(distinct e.employee_code)
from Company
join Lead_Manager as lm on Company.company_code = lm.company_code
join Senior_Manager as sm on Company.company_code = sm.company_code
join Manager as m on Company.company_code = m.company_code
join Employee as e on Company.company_code = e.company_code
GROUP BY Company.COMPANY_CODE, Company.FOUNDER
ORDER BY Company.COMPANY_CODE ASC
Basically, you are using an aggregate function so you need to group
select count(amount) from Orders group by customer_id
Orders
order_id item amount customer_id
1 Keyboard 400 4
2 Mouse 300 4
3 Monitor 12000 3
4 Keyboard 400 1
5 Mousepad 250 2
Now using group by on customer_id so we have id 4 so need to check the count of 4 id with group by

How to display top 5 and bottom 5 in same query with join?

I'm struggling to find a way to combine these two queries into one so that only one table is viewed. I want to display the top 5 and bottom 5 categories based on the number of members in each category.
SELECT
category_name,
members
From category c
JOIN grp g ON c.category_id=g.category_id
GROUP by category_name
ORDER BY members DESC
LIMIT 5;
SELECT
category_name,
members
From category c
JOIN grp g ON c.category_id=g.category_id
GROUP by category_name
ORDER BY members
LIMIT 5;
I've tried union and multiple select statements but always end up with an error for "subquery returns more than 1 row" or inccorect syntax. Any help would be appreciated.
If you are going to do unions with ORDER and LIMIT clauses, you will have to "hide" these clauses within subqueries:
SELECT * FROM (
SELECT
category_name,
members
From category c
JOIN grp g ON c.category_id=g.category_id
GROUP by category_name
ORDER BY members DESC
LIMIT 5
) SQ1
UNION
SELECT * FROM (
SELECT
category_name,
members
From category c
JOIN grp g ON c.category_id=g.category_id
GROUP by category_name
ORDER BY members
LIMIT 5
) SQ2

MYSQL JOIN query to group user skills for conditional count

I am struggling to find the logic for a JOIN query with GROUP BY.
I have 3 tables.
1. tbl_users
2. tbl_event_orders
3.tbl_event_signature ( For saving signatures on completed events)
tbl_users
id name skill
---------------------------
1 user1 A
2 user2 B
3 user3 A
4 user4 A
tbl_orders
id user_id item_id price
------------------------------------
1 1 1 100
2 2 1 100
3 3 1 100
4 4 1 100
tbl_signature
id item_id user_id signature
----------------------------------------------
1 1 1 xxxxxxxx...
1 1 3 NULL
1 1 4 xxxxxxxx...
I need the event details from item id.
For example for item with id 1, I need the following result.
skill total_count attended_users_count amount
A 3 2 300
B 1 0 100
skill - skill from user table.
total_count - total count of orders from that partical skill.
attended_users_count - total count of orders from that partical skill + this should have an entry and a NOT NULL value in tbl_signature table.
amount - sum of price(total_count)
I have the following query for getting users with skills and total count.
SELECT
U.skill as skill,
count(U.skill) as total_count,
sum( O.price ) as amount
FROM tbl_users U
INNER JOIN tbl_orders O
ON U.id = O.user_id
WHERE O.item_id = 1
GROUP BY U.skill
but when dealing with attended users count, I am getting unexpected results.
I have tried with the following query,
SELECT
U.skill as skill,
count(U.skill) as total_count,
count( S.signature ) as attended_users_count,
sum( O.price ) as amount
FROM tbl_users U
INNER JOIN tbl_orders O
ON U.id = O.user_id
LEFT JOIN tbl_signature S
ON O.item_id = S.item_id
WHERE O.item_id = 1
GROUP BY U.skill
Is there any way to get this in a single query?
This query should give you the results you want. It JOINs tbl_orders to tbl_users, and then LEFT JOINs to tbl_signature. Rows of tbl_signature which don't match, or which don't have a signature, will not get included in the count for that order:
SELECT u.skill,
COUNT(o.id) AS total_count,
COUNT(s.signature) AS attended_users_count,
SUM(o.price) AS amount
FROM tbl_orders o
JOIN tbl_users u ON u.id = o.user_id
LEFT JOIN tbl_signature s ON s.item_id = o.item_id AND s.user_id = u.id
WHERE o.item_id = 1
GROUP BY u.skill
Output:
skill total_count attended_users_count amount
A 3 2 300
B 1 0 100
Demo on dbfiddle

Order data by data from another table

I have two tables:
rooms (all the rooms)
id | title | ...
-----------------
1 |Room 1 |
2 |Room 2 |
3 |Room 3 |
user_rooms (in which room is every user, column user is user's id and it's primary column)
user | room | ...
------------------
20 | 3 |
14 | 1 |
35 | 3 |
So I want to select all the rooms from the 'rooms' table but to order them in that way to show the rooms with the most users in them and after that the rooms with less and less users. For example, I want to show room 3 first (because 2 users are in it), then room 1 (one user in it), and finally room 2 (since no users are in it). How to achieve that?
SELECT aa.id, aa.title
FROM rooms AS aa
LEFT JOIN (
SELECT room, COUNT(*) AS total_count
FROM user_rooms
GROUP BY room
) AS _aa
ON aa.id = _aa.room
ORDER BY _aa.total_count;
This would often be done without a subquery:
select r.id, r.title, count(ur.room) as numusers
from rooms r left join
user_rooms ur
on r.id = ur.room
group by r.id, r.title
order by numusers desc;
This would often be more efficient than a version using a subquery in the from clause because it can take advantage of an index on the join key.
Interestingly, the same index would be used for a correlated subquery in the select, which is an alternative approach:
select r.id, r.title,
(select count(*)
from user_rooms ur
where r.id = ur.room
) as numusers
from rooms r
order by numusers desc;
This might be the most efficient approach, because it removes the aggregation in the outer query.
select r.id, r.title, coalesce(t.cnt,0)
from rooms r left join
(select room, count(*) as cnt
from user_rooms
group by room) t on t.room = r.id
order by t.cnt desc
This will give you only rooms with users
SELECT title, count(user) As MostUsers
FROM Rooms R
INNER JOIN user_rooms U
ON R.?field? = U.?field?
GROUP BY title
ORDER BY MostUsers
You need to complete the query inserting the names of the fields that you can use to Join the tables
If you want all rooms you can use a Left Join:
SELECT title, count(user) As MostUsers
FROM Rooms R
LEFT JOIN user_rooms U
ON R.?field? = U.?field?
GROUP BY title
ORDER BY MostUsers
Please try the following query:
select * from rooms r
order by (select count(1)
from userroom ur
where ur.roomid = r.roomid ) desc

Select rows in order of total count

I have a table of users which hold a a users id that they voted for like this:
uid | voted_for
1 | 3
2 | 3
3 | 1
What i'm aiming to do is order uid based on how many people have voted for that uid. But I have no idea how to do it.
So the end result would be:
uid | Total_Votes
3 | 2
1 | 1
2 | 0
Hope you can help explain the best way to structure the SQL for this.
Perhaps something like this will help joining the table on itself:
SELECT u.*, voted_for_cnt
FROM users u
LEFT JOIN (
SELECT voted_for, count(1) voted_for_cnt
FROM users
GROUP BY voted_for
) t ON u.uid = t.voted_for
ORDER BY t.voted_for_cnt DESC
SQL Fiddle Demo
This simple query will produce the output you requested:
select voted_for as uid, count(*) as total_votes
from users
group by 1
order by 2 desc
If you want all data about each user in the output, join users to itself:
select u.*, count(v.uid) as total_votes
from users u
left join users v on v.voted_for = u.uid
group by 1,2,3,4,5 -- put as many numbers here as there are columns in the users table
order by total_votes desc
This second query will give a total_votes score of zero if no one voted for the user.
Alternatively, you can select only those columns you want:
select u.uid, u.name, count(v.uid) as total_votes
from users u
left join users v on v.voted_for = u.uid
group by 1,2
order by 3 desc
```
To return only the winners, do this:
select u.uid, u.name, count(*) as total_votes
from users u
left join users v on v.voted_for = u.uid
group by 1,2
having count(*) = (
select max(c) from (
select count(*) as c from users group by voted_for))
order by 3 desc