How do add data to multiple columns at the same time - mysql

I got this last task before I can go to bed...
Make a query that shows the name(not the id) of players who have won the lottery more than once, how many times they've won and the name(not the id) of the municipality they live in.
Players-table: PlayerNum, Name, Address, MunicipalityID
Winners-table: PlayerNum, DrawID
Municipality-table: MunicipalityID, County, Population, Name
Thank you sooo much in advance!!

You need to join the tables and do a sub query on the winner table using count and group by the join the result set with player
Not sure what the draw table does

You really should make an attempt instead of just asking for the solution.
Your starting point is to find the users who have won more than once. This is a simple GROUP BY of PlayerNum and the HAVING clause to limit the result based on the COUNT -
SELECT PlayerNum, COUNT(DrawID) AS num_wins
FROM Winners
GROUP BY PlayerNum
HAVING num_wins > 1
The next step is to add the names of the players. For this you need to join to the Players table and I have added table aliases (w & p) to avoid retyping the full table name each time -
SELECT p.Name, COUNT(DrawID) AS num_wins
FROM Winners w
INNER JOIN Players p
ON w.PlayerNum = p.PlayerNum
GROUP BY w.PlayerNum
HAVING num_wins > 1
And then finally the join to Municipality to get the Name with a column alias as we already have a Name column -
SELECT p.Name, COUNT(DrawID) AS num_wins, m.Name AS MunName
FROM Winners w
INNER JOIN Players p
ON w.PlayerNum = p.PlayerNum
INNER JOIN Municipality m
ON p.MunicipalityID = m.MunicipalityID
GROUP BY w.PlayerNum
HAVING num_wins > 1

Related

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

SQL join tables and get Average

I asked yesterday a little bit similar question (I thought that that was my problem but later i realised that there was a fault). But that question got couple of nice answers and it did not make sense to change that question. And i think this question is enough different.
Question:
I have four tables and i need to calculate the Average points that each School has gotten.
Problem: the School Average should be calculated by the two latest Points each Team has gotten. At the moment the Query calculates all the points a Teams has gotten in the average.
A School can have multiple Teams and Teams can have multiple points. And from each team only the two latest points should be calculated in the School Average. Each School should also get the proper City KAID (CITY_ID). In the sqlFiddle everything works but the Average is wrong because it calculates all the points a Team has gotten.
I have created a simplificated working: sqlFiddle
The average for SCHOOL1 should be 2,66...
Example:
Let's say that Team10 has 6 points:
TEAM10 3..4..7..0..3..5 = 8 (3+5=8)
Only the latest two points should be calculated in the average (3 and 5). This should happen for all the teams.
I have tried couple of Queries but they don't work.
Query 1 (Problem: calculates all the points):
SELECT SNAME As School, AVG(PTS) As Points, ka.KAID As City_id FROM
Schools op
LEFT JOIN Points pi
ON op.OPID = pi.OPID
LEFT JOIN Citys ka
ON op.KAID = ka.KAID
GROUP BY SNAME, ka.KAID
ORDER BY City_id, Points, School ASC
Query 2 (Problem: Average wrong and duplicates):
SELECT IFNULL(AVG(PTS), 0) AS AVG, po2.KAID AS KID, SNAME AS SNAM FROM
(
SELECT te1.ID, te1.KAID, po1.PTS, te1.OPID FROM Points po1
INNER JOIN Teams te1 ON te1.ID = po1.TEID
GROUP BY po1.TEID, te1.ID HAVING count(*) >= 2
)
po2 INNER JOIN Schools sch1 ON po2.KAID = sch1.KAID
GROUP BY sch1.SNAME, sch1.OPID
ORDER BY po2.ID DESC
I am quite new to sql I have tried different Queries but i haven't gotten this to work properly.
If something is not clear please ask i will try to Explain it better.
try running this...
SELECT
SNAME As School,
SUM(pts)/ count(*) As Points,
ka.KAID As City_id
FROM Schools op
LEFT JOIN Points pi
ON op.OPID = pi.OPID
LEFT JOIN Citys ka
ON op.KAID = ka.KAID
GROUP BY SNAME, ka.KAID
ORDER BY City_id, Points, School ASC
DEMO
From what I see you have for the first school and the first city 8 rows with the sum = 29.
29/8 = 3.25.. you are joining the tables on the correct fields and the query is returning the rows in the table based on the opid and kaid so it seems the results are correct.. i'm guessing the avg function is not including the 0's or something but the results are there
EDIT:
to get it for the two newest rows you need to look at the greatest id per school and then the second greatest.. this will do what you want.
SELECT
SNAME As School,
SUM(pts)/ count(*) As Points,
ka.KAID As City_id
FROM Schools op
LEFT JOIN Points pi ON op.OPID = pi.OPID
LEFT JOIN Citys ka ON op.KAID = ka.KAID
JOIN
( ( SELECT MAX(id) as f_id
FROM points
GROUP BY TEID
ORDER BY f_id
)
UNION
( SELECT p1.id
FROM
( SELECT MAX(id) as t_id
FROM points
GROUP BY TEID
ORDER BY t_id
)t
LEFT JOIN points p1 on p1.id = (t.t_id -1)
)
) temp ON temp.f_id = pi.id
GROUP BY SNAME, ka.KAID
ORDER BY City_id, Points, School ASC;
ANOTHER DEMO

MySQL Query Never Returns

EDIT: This has been solved, requiring a subquery into the appearances table. Here is the working solution.
SELECT concat(m.nameFirst, ' ', m.nameLast) as Name,
m.playerID as playerID,
sum(b.HR) as HR
FROM Master AS m
INNER JOIN Batting AS b
ON m.playerID=b.playerID
WHERE ((m.weight/(m.height*m.height))*703) >= 27.99
AND m.playerID in (SELECT playerID FROM appearances GROUP BY playerID HAVING SUM(G_1b+G_dh)/SUM(G_All) >= .667)
GROUP BY playerID, Name
HAVING HR >= 100
ORDER BY HR desc;
I'm working with the Lahman baseball stat database, if anyone's familiar.
I'm trying to retrieve a list of all large, slugging first basemen, and the data I need is spread across three different tables. The way I'm doing this is finding players of a minimum BMI, who have spent at least 2/3 of their time at first/designated hitter, and have a minimum number of home runs.
'Master' houses player names, height, weight (for BMIs).
'Batting' houses HR.
'Appearances' houses games played at first, games played at DH, and total games.
All three databases are connected by the same 'playerID' value.
Here is my current query:
SELECT concat(m.nameFirst, ' ', m.nameLast) as Name,
m.playerID as playerID,
sum(b.HR) as HR
FROM Master AS m
INNER JOIN Batting AS b
ON m.playerID=b.playerID
INNER JOIN Appearances AS a
ON m.playerID=a.playerID
GROUP BY Name, playerID
HAVING ((m.weight/(m.height*m.height))*703) >= 27.99
AND ((SUM(IFNULL(a.G_1b,0)+IFNULL(a.G_dh,0)))/SUM(IFNULL(a.G_All,0))) >= .667
AND HR >= 200
ORDER BY HR desc;
This appears correct to me, but when entered it never returns (runs forever) - for some reason I think it has something to do with the inner join of the appearances table. I also feel like there's a problem with combining m.weight/m.height in a "HAVING" clause, but with aggregates involved I can't use "WHERE." What should I do?
Thanks for any help!
EDIT: After removing all conditionals, I'm still getting the same (endless) result. This is my simpler query:
SELECT concat(m.nameFirst, ' ', m.nameLast) as Name,
m.playerID as playerID,
sum(b.HR) as HR
FROM Master AS m
INNER JOIN Batting AS b
ON m.playerID=b.playerID
INNER JOIN Appearances AS a
ON m.playerID=a.playerID
GROUP BY playerID, Name
ORDER BY HR desc;
My guess is that the problem with your query is that each player has appeared many times (appearances) and at bat many times. Say a player has been at bat 1000 times in 100 games. Then the join -- as you have written it -- will have 100,000 rows just for that player.
This is just a guess because you have provided no sample data to verify if this is the problem.
The solution is to pre-aggregate the appearances and games tables as subqueries (at the playerId level) and then join them back.

mysql Left Join, group by with count

I have two tables - one for courses and one for people attending the course.
Both are joined by course_id
table 1: firstaid - has all the course names
table 2: first_aid_att - records attendees and captures first aid
course id
I would like to get a count of attendees per course.
I have got a join working but don't know how to do the group by and count.
SELECT *
FROM firstaid
LEFT JOIN first_aid_att ON firstaid.course_id = first_aid_att.course_id
ORDER BY `sortDate` ASC
Try this:
SELECT f1.*, COUNT(f2.course_id)
FROM firstaid f1
LEFT JOIN first_aid_att f2 ON (f1.course_id = f2.course_id)
GROUP BY f1.course_id
ORDER BY f2.sortDate

MYSQL View and summing fields

I need some help I have been scouring the web and haven't been able to find something too similar. I have a MYSQL database for my Golf League. I need to display standings by creating a view from this database. There are 2 people per team, my primary key in 'players' is 'id' there is also a teamID (numerical value 1 - 20, 20 teams) for each player which corresponds to their teammates. Basically what I need is a view that contains 'teamID', both players 'LName' (maybe an 'LNameA','LNameB'), and a sum of the two players 'points' field. I have never summed a field from one person and another or created a view in MYSQL.
EDIT:
I was trying something like
CREATE
VIEW standings1
AS SELECT teamID, LName, points
FROM players
but need teamID to be the primaryKey of the view which will contain each players last name, and their points summed together.
Try this:
create view standings as
select teamId, group_concat(lname separator ', ') as TeamMembers,
sum(points) TotalPoints from players
group by teamId
Oh, one more thing. If you want to have the names of the players in different fields (group_concat just separate them by commas, but it is still a single field) you can use this query:
create view standings as
select a.teamId, a.lname as player1, b.lname as player2,
a.points + b.points TotalPoints
from players a
join players b ON a.teamId = b.teamId AND a.id >= b.id
group by a.teamId, a.id
having count(*) = 2
That way you can play better with the names in PHP without having to parse the ", "
If I understand your table structure, you will need a JOIN against the table's own teamID. I'm assuming the teamID refers to a team, and is not the id of the player. The trick here is to join two copies of the table on the same teamID, but where the player ids are non-equal. That should produce the pair of players per team.
CREATE VIEW standings AS
(
SELECT
p1.teamID AS teamID,
p1.id AS p1id,
p2.id AS p2id,
p1.LName AS p1LName,
p2.LName AS p2LName,
p1.score + p2.score AS totalScore
FROM
/* JOIN on matching teamID and non-matching player-id (so you don't get the same player twice) */
players p1 JOIN players p2 ON p1.teamID = p2.teamID and p1.id <> p2.id
);