Select the employee who earned more - mysql

[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

Related

Unknown column in 'on clause' after MySQL upgrade

I've been updating some old code which used PHP4 and MySQL 4.1 up to MySQL 5.6 / MariaDB 10. I've had a few issues with SQL JOINs
and precedence but this one has really stumped me and is giving me the error -
#1054 - Unknown column 'grouping_id' in 'on clause'
I've tried messing about with the order of the JOIN statements in the query below but I haven't had any success yet, as mentioned this query worked fine on MySQL 4.
SELECT
team.team_id,
team.team_name,
competition.rel_sport_id,
country.country_name
FROM
team
LEFT JOIN team_grouping ON(
rel_team_id = team_id AND team_grouping.rel_grouping_id = grouping_id
)
LEFT JOIN grouping ON grouping_id = team_grouping.rel_grouping_id
LEFT JOIN country ON team.rel_country_id = country_id
LEFT JOIN sport ON team.rel_sport_id = sport_id
LEFT JOIN competition_country ON(
rel_competition_id = competition_id AND competition_country.rel_country_id = country_id
)
LEFT JOIN competition ON competition_id = '985'
WHERE
team.rel_country_id = competition_country.rel_country_id AND team.rel_sport_id = competition.rel_sport_id AND grouping_id = '3'
ORDER BY
team_name
Can anyone help with what could be wrong with the above query?
EDIT - Added table schemas:
CREATE TABLE `grouping` (
`grouping_id` int(11) NOT NULL AUTO_INCREMENT,
`grouping_name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`grouping_id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin
CREATE TABLE `team` (
`team_id` int(11) NOT NULL AUTO_INCREMENT,
`team_name` varchar(200) DEFAULT NULL,
`image` varchar(100) DEFAULT NULL,
`rel_country_id` int(11) DEFAULT NULL,
`rel_sport_id` int(11) DEFAULT NULL,
`modified_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`team_id`),
KEY `IDX_team_1` (`rel_country_id`),
KEY `IDX_team_2` (`rel_sport_id`)
) ENGINE=MyISAM AUTO_INCREMENT=11918 DEFAULT CHARSET=latin1
CREATE TABLE `country` (
`country_id` int(11) NOT NULL AUTO_INCREMENT,
`country_name` varchar(40) DEFAULT NULL,
`image` varchar(40) DEFAULT NULL,
`rel_geographic_id` int(11) DEFAULT NULL,
PRIMARY KEY (`country_id`),
KEY `IDX_country_2` (`rel_geographic_id`)
) ENGINE=MyISAM AUTO_INCREMENT=237 DEFAULT CHARSET=latin1
CREATE TABLE `competition` (
`competition_id` int(11) NOT NULL AUTO_INCREMENT,
`competition_name` varchar(200) DEFAULT NULL,
`rel_sport_id` int(11) DEFAULT NULL,
`rel_grouping_id` int(11) DEFAULT NULL,
`rel_competition_tz_id` int(11) NOT NULL DEFAULT '2',
`modified_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`competition_id`),
KEY `IDX_competition_1` (`rel_sport_id`),
KEY `IDX_competition_2` (`rel_grouping_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1133 DEFAULT CHARSET=latin1
CREATE TABLE `sport` (
`sport_id` int(11) NOT NULL AUTO_INCREMENT,
`sport_name` varchar(40) DEFAULT NULL,
`image` varchar(40) DEFAULT NULL,
`modified_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`sport_id`)
) ENGINE=MyISAM AUTO_INCREMENT=29 DEFAULT CHARSET=latin1
CREATE TABLE `competition_country` (
`rel_competition_id` int(11) NOT NULL DEFAULT '0',
`rel_country_id` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`rel_competition_id`,`rel_country_id`),
KEY `IDX_competition_country_1` (`rel_competition_id`),
KEY `IDX_competition_country_2` (`rel_country_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Table names in an ON clause can only refer to tables preceding it in the query. When you're joining through a relationship table, the first ON clause just relates with the table before it, you relate to the second table in the next ON clause.
So the ON clause for team_grouping should only have rel_team_id = team_id, and the ON clause for competition_country should only have rel_country_id = country_id.
I don't think you need the WHERE clause at the end. Those relationships should be implied already by the earlier joins. And since you're doing a LEFT JOIN with grouping, you should put restrictions on that table in the ON clause; otherwise, the null values from non-matching rows will be filtered out by the WHERE clause.
SELECT
team.team_id,
team.team_name,
competition.rel_sport_id,
country.country_name
FROM team
LEFT JOIN team_grouping ON rel_team_id = team_id
LEFT JOIN grouping ON grouping_id = team_grouping.rel_grouping_id AND grouping_id = 3
LEFT JOIN country ON team.rel_country_id = country_id
LEFT JOIN sport ON team.rel_sport_id = sport_id
LEFT JOIN competition_country ON competition_country.rel_country_id = country_id
LEFT JOIN competition ON competition_id = '985' AND competition_id = competition_country.rel_competition_id
ORDER BY team_name

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

join count per chatroom

i have tried different join examples from w3c site, but could not solve my problem.
All i could get working was:
SELECT *
FROM chatters_online
WHERE TIME_TO_SEC(TIMEDIFF(NOW(),datumtijd )) < 300
But i want is a count of chatters per chatroom: room1(12),room12(2) etc.
CREATE TABLE IF NOT EXISTS `chatters_online` (
`room` int(10) unsigned NOT NULL,
`datumtijd` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`chatterID` int(10) unsigned NOT NULL DEFAULT '0',
`nick` varchar(20) NOT NULL,
UNIQUE KEY `unique_index` (`room`,`nick`),
KEY `room` (`room`),
KEY `nick` (`nick`),
KEY `datumtijd` (`datumtijd`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `chatrooms` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`roomname` varchar(20) NOT NULL,
`moderator` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `roomname` (`roomname`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=18 ;
What i am looking for is the needed SQL for a count per chatroom.
JOIN and GROUP BY should give you the required results
select CR.roomname, count(CO.chatterID) as ChattersCount
FROM chatrooms CR
JOIN chatters_online CO
on CO.room = CR.id
GROUP BY CR.roomname

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

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

mysql aggregate difficulties

I have two table structures in my database:
CREATE TABLE `projects` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`description` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
CREATE TABLE `issues` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_id` varchar(10) DEFAULT NULL,
`project_id` int(11) DEFAULT NULL,
`name` varchar(32) DEFAULT NULL,
`description` varchar(128) DEFAULT NULL,
`date_created` date DEFAULT NULL,
`type` enum('general','bug','requirement') DEFAULT NULL,
`priority` enum('low','medium','high') DEFAULT NULL,
`status` enum('resolved','open','discarded') DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `member_id` (`member_id`),
KEY `project_id` (`project_id`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
What I am trying to do is create a select statement that returns the project name, and the number of resolved issues that are associated with that project. I have created the following SQL statement:
select projects.name, count(*) from projects left join issues on projects.id = issues.project_id where status = 'resolved' group by projects.name
However this only returns projects that have at least one resolved issue, I need it to return projects that have 0 resolved issues as well.
It's been a while since I have done any mySQL, can anyone help out? Thanks.
I thought I'd give some more information since I haven't received a working answer yet. If I had four projects and one issue for each project, with two of those issues being 'resolved', I'd expect the query to return:
project_name | count(*)
--------------------------
first_project | 1
second_project | 0
third_project | 0
fourth_project | 1
However, the query is only returning projects that have at least one resolved issue.
project_name | count(*)
-------------------------
first_project | 1
fourth_project | 1
change your query to:
SELECT p.name, count(i.*)
FROM PROJECTS p
LEFT JOIN ISSUES i ON p.id = i.project_id
AND i.status = 'resolved'
GROUP BY projects.name
having "status = 'resolved'" in the where clause caused it only to return those projects with at least one issue