how to create a team leaderboard with info from 4 tables? - mysql

This is tricky, I have been tasked with creating an team leader board where individuals complete tasks for a score. The score is defined in the table "station" and every time a user completes a task- a post is created in the posts table with the id of the station and their RFID (radio frequency ID). There is a team table which defines the team name.
i need a way to get the sum of all the post scores (joined points from stations table) a teams members have participated in.
The result should be sorted be team score and look something like if we have 4 teams with 4 members who participated in 4 events- whats the total score for each team
Team name one (Teams.name) | score
Team name two (Teams.name) | score
Team name three (Teams.name) | score
The tables -
CREATE TABLE `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rfid` varchar(50) NOT NULL,
`station_id` int(11) NOT NULL,
`updated_at` datetime NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
-- --------------------------------------------------------
Table structure for table stations
CREATE TABLE `stations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`description` text NOT NULL,
`points` int(11) NOT NULL,
`logic` varchar(200) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1023 ;
-- --------------------------------------------------------
Table structure for table teams
CREATE TABLE `teams` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
-- --------------------------------------------------------
Table structure for table users
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rfid` varchar(50) NOT NULL,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`team` int(11) NOT NULL,
`quiz_score` int(11) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
I have created an query for an individual leaderboard-
SELECT users.first_name, users.last_name, posts.rfid, sum(stations.points) score
FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
GROUP BY posts.rfid
ORDER BY score DESC LIMIT 0 , 100
this is what i have got so far for the team one
SELECT name, (SELECT sum(stations.points) score FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
WHERE users.team = teams.id
GROUP BY posts.rfid) team_score FROM teams
//subquery returns more than one row
I think this might be the correct answer
SELECT name,
(SELECT sum(stations.points) score FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
WHERE users.team = teams.id ) team_score
FROM teams

Related

Merge the rows and give me the total count

I want to count how many unique games a user have been played. Here's how the current SQL query looks like:
SELECT COUNT(DISTINCT d.id_game) AS c
FROM discord AS d
JOIN discord_games AS dg
ON d.id_game = dg.id
WHERE d.id_user = '1'
AND d.id_game != '0'
GROUP BY d.id_game
ORDER BY dg.data_name ASC
And here's now the database looks like:
CREATE TABLE IF NOT EXISTS `discord` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_user` int(11) NOT NULL,
`id_channel` varchar(50) NOT NULL,
`id_game` int(11) NOT NULL,
`data_muted_server` tinyint(4) NOT NULL,
`data_muted_self` tinyint(4) NOT NULL,
`data_deafen_server` tinyint(4) NOT NULL,
`data_deafen_self` tinyint(4) NOT NULL,
`data_suppressed` tinyint(4) NOT NULL,
`data_status` varchar(10) NOT NULL,
`datetime_logged` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `discord_games` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data_name` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `discord_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data_id` text NOT NULL,
`data_name` varchar(50) NOT NULL,
`data_avatar` text,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
)
The SQL query counts correctly but it only counts 1 per row.
Example of how I'm thinking. If the user with the ID 1 have played the same game 24 times (for an example Battlefield 3) it will return 1 played game. If the same user plays another game 37 times, it will return 2 played games and so on.
SUM(DISTINCT ... doesn't work since it only replace 1 with the game ID.
How can I sum the rows so it displays the number 2 instead of 2 rows?
You could just remove the group by property and count the distinct games played. It will return the number of distinct gamesp layed by the user 1
SELECT COUNT(DISTINCT d.id_game) AS c
FROM discord AS d
JOIN discord_games AS dg
ON d.id_game = dg.id
WHERE d.id_user = '1'
AND d.id_game != '0'
ORDER BY dg.data_name ASC

Inner join 3 tables and calculate the average value on a field

There are 3 tables:
medics:
IDM (id_medic) (primary key)
1st name
2nd name
specialty
patients:
IDP (id_patient) (primary key)
name
DOB (date of birth)
visits:
id
id_medic
id_patient
I would like to find out the average age of patients for each specialty.
SELECT specialty, AVG(year(curdate()) - year(patients.DOB))
FROM medics, patients, visits
WHERE medics.IDM = visits.medics GROUP by specialty;
The query above shows me on each line the average of all patients.
Try it:
SELECT
Speciality,
ROUND(AVG(YEAR(NOW())-YEAR(DOB)),0) AS Years
FROM visits
INNER JOIN medics
ON visits.IdMedic = medics.Id
INNER JOIN patients
ON visits.IdPatient = patients.Id
GROUP BY Speciality
My tables:
CREATE TABLE `visits` (
`Id` int(11) NOT NULL,
`IdMedic` int(11) DEFAULT NULL,
`IdPatient` int(11) DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `patients` (
`Id` int(11) NOT NULL,
`Name` varchar(45) DEFAULT NULL,
`DOB` date DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `medics` (
`Id` int(11) NOT NULL,
`Name` varchar(45) DEFAULT NULL,
`Speciality` varchar(45) DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Between a MIN and MAX date in joined table

I have a table called Booking and a table called FacilityBooking. A booking is a composition of facility bookings, a one to many relation. The date and time of the booking is determined by the lowest start date, and the highest end date of the facility bookings that belongs to it.
I want to pull some statistics of how many private and how many business bookings there has been between two dates.
CREATE TABLE `Booking` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`comments` varchar(255) DEFAULT NULL,
`createdBy` varchar(255) DEFAULT NULL,
`customerName` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`isPaid` bit(1) DEFAULT NULL,
`isPrivateClient` bit(1) DEFAULT NULL,
`needsPermission` bit(1) DEFAULT NULL,
`phoneNumber` varchar(255) DEFAULT NULL,
`referenceNumber` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# Dump of table FacilityBooking
# ------------------------------------------------------------
CREATE TABLE `FacilityBooking` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`comments` varchar(2000) DEFAULT NULL,
`from` datetime DEFAULT NULL,
`to` datetime DEFAULT NULL,
`bookablePlace_id` int(11) DEFAULT NULL,
`booking_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_2tv9w7g5vyx9po8vs6ceogldb` (`bookablePlace_id`),
KEY `FK_n17h188ecbdos5lsva51b8j29` (`booking_id`),
CONSTRAINT `FK_n17h188ecbdos5lsva51b8j29` FOREIGN KEY (`booking_id`) REFERENCES `Booking` (`id`),
CONSTRAINT `FK_2tv9w7g5vyx9po8vs6ceogldb` FOREIGN KEY (`bookablePlace_id`) REFERENCES `BookablePlace` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I have created an sqlfiddle: http://sqlfiddle.com/#!9/7ae95/2
And this is what i have so far:
SELECT
CASE isPrivateClient
WHEN 0 THEN "business"
WHEN 1 THEN "private"
END AS clientType,
count(isPrivateClient) as count
FROM
Booking
GROUP BY
isPrivateClient
So what i need from here is to join the facilitybookings and search between the lowest from date and the highest to date.
Hope someone can help me :)
Join the FacilityBooking table and filter using WHERE:
SELECT
CASE isPrivateClient
WHEN 0 THEN "business"
WHEN 1 THEN "private"
END AS clientType,
count(FacilityBooking.id) as count
FROM
Booking INNER JOIN FacilityBooking ON
Booking.id = FacilityBooking.booking_id
-- Between 2015-05-01 AND 2015-06-01 INCLUSSIVE'
WHERE FacilityBooking.from <= '2015-06-01' AND FacilityBooking.to >= '2015-05-01'
GROUP BY
isPrivateClient
fixed fiddle
If you want to only include "full" Booking in which all FacilityBooking are between 2 date, something like this should do the trick :
SELECT clientType, count(bookId)
FROM (
SELECT
b.id as bookId,
CASE b.isPrivateClient
WHEN 0 THEN "business"
WHEN 1 THEN "private"
END AS clientType,
Min(fb.from) as minFrom,
Max(fb.to) as maxTo
FROM
Booking b
INNER JOIN FacilityBooking fb ON b.id = fb.booking_id
GROUP BY bookId
) tbl
WHERE minFrom >= '2015-05-22' -- Min Date
AND maxTo <= '2015-05-24' -- Max Date
GROUP BY
clientType

i get wrong results from mysql join query

I have 2 tables, that i want to join, one is rooms and another is reservations.
Basically I want to search for rooms which are not reserved (not in reservation table) and to get the details of those rooms (which are not in reservation table) from room table.
Here are my tables structure:
CREATE TABLE `room` (
`roomID` int(11) NOT NULL AUTO_INCREMENT,
`hotelID` int(11) NOT NULL,
`roomtypeID` int(11) NOT NULL,
`roomNumber` int(11) NOT NULL,
`roomName` varchar(255) NOT NULL,
`roomName_en` varchar(255) NOT NULL,
`roomDescription` text,
`roomDescription_en` text,
`roomSorder` int(11) NOT NULL,
`roomVisible` tinyint(4) NOT NULL,
PRIMARY KEY (`roomID`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8;
CREATE TABLE `reservation` (
`reservationID` int(11) NOT NULL AUTO_INCREMENT,
`customerID` int(11) NOT NULL,
`hotelID` int(11) NOT NULL,
`reservationCreatedOn` datetime NOT NULL,
`reservationCreatedFromIp` varchar(255) CHARACTER SET greek NOT NULL,
`reservationNumberOfAdults` tinyint(4) NOT NULL,
`reservationNumberOfChildrens` tinyint(4) NOT NULL,
`reservationArrivalDate` date NOT NULL,
`reservationDepartureDate` date NOT NULL,
`reservationCustomerComment` text CHARACTER SET greek,
PRIMARY KEY (`reservationID`)
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;
CREATE TABLE `reservationroom` (
`reservationroomID` int(11) NOT NULL AUTO_INCREMENT,
`reservationID` int(11) NOT NULL,
`hotelID` int(11) NOT NULL,
`roomID` int(11) NOT NULL,
PRIMARY KEY (`reservationroomID`)
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;
Here is the query that I have right now, which gives me wrong results:
SELECT * FROM room r
LEFT JOIN reservation re
ON r.hotelID = re.hotelID
WHERE re.hotelID = 13
AND NOT
(re.reservationArrivalDate >= '2014-07-07' AND re.reservationDepartureDate <= '2014-07-13')
I also have created a fiddle, with the data from both tables included:
http://sqlfiddle.com/#!2/4bb9ea/1
Any help will be deeply appreciated
Regards, John
i agree that room number was missed,
but query template should looks like
SELECT
*
FROM
room r
LEFT JOIN reservation re
ON r.hotelID = re.hotelID
WHERE r.hotelID = 2
AND NOT (
re.hotelID IS NOT NULL
AND re.reservationArrivalDate >= '2014-07-07'
AND re.reservationDepartureDate <= '2014-09-23'
) ;
You need change table in where statement from reservation to room. Also you need add re.hotelID to where statement as well, because on where statement you need check that record is not null ans only after try to check dates
Given the newly-added reservationroom table, consider using a NOT EXISTS sub-query to find rooms without reservations:
SELECT
*
FROM
room r
WHERE NOT EXISTS
(SELECT
*
FROM
reservationroom rr
WHERE
rr.reservationroomID = r.roomID
)

Select the employee who earned more

[MySQL] I want to select the employee who earned more, the problem is that I am using two tables.
Finally I have no idea how to do it.
I built a query that can count the number of services and sort by most, but the query is flawed as there services with higher values​​.
here is the table structure.
CREATE TABLE IF NOT EXISTS `contas` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_servico` int(11) DEFAULT NULL,
`id_funcionario` int(11) DEFAULT NULL,
`data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=28 ;
CREATE TABLE IF NOT EXISTS `servicos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`titulo` varchar(250) NOT NULL COMMENT 'Título do serviço',
`descri` mediumtext COMMENT 'uma pequena descrição do serviço',
`valor` varchar(10) NOT NULL COMMENT 'valor bruto do serviço',
`comissao` varchar(10) DEFAULT NULL COMMENT 'comissão por funcionario',
`data` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
Select all employees, join their "services", then group by employee ID, sum their income and select the first one.
SELECT E.id, SUM(S.amount) AS income
FROM employee E
INNER JOIN service S ON S.employee_id = E.id
GROUP BY E.id
ORDER BY income DESC
LIMIT 1