mysql query but two differant group by - mysql

If my Data is
Name - playerID - matchID - Innings - Runs
James 1 1 1 5
James 1 1 2 8
Darren 2 1 1 3
Darren 2 1 2 9
James 1 2 1 10
James 1 2 2 12
Darren 2 2 1 13
Darren 2 2 2 19
and my sql data is
$query = "SELECT playerID, name,
SUM(runs) AS runs_scored,
MAX(runs) AS highest_score
FROM matchPlayer GROUP BY playerID";
Then the output would read
James has scored 35 runs with a highest score of 18
Darren has scored 44 runs with a highest score of 19
Now I wish to get the highest total scored in one match (that is combining innings 1 & 2)?
I have no idea how to start on this query :(
EDIT
The exact info I require is the HIGHEST match total, so James has 13 combined runs from matchID 1 and 22 combined runs from matchID 2 - so the answer I am after is 22.

You need to do it in two stages:
SELECT ms.playerID, mp.name, SUM(ms.runs_by_match) AS runs_scored,
MAX(ms.runs_by_match) as highest_score
FROM
matchPlayer as mp
INNER JOIN (
SELECT playerID, matchID, SUM(runs) AS runs_by_match
FROM matchPlayer
GROUP BY playerID, matchID
) AS ms ON mp.playerID = ms.playerID
GROUP BY
ms.playerID, mp.name

Related

Grouping in Mysql

i need to get the top touristCount in each month like January Zambia has 4 touristCount i need to select only Zambia for January and so on
user
`useri_id` | `username` | `email` | `nationality`
1 Joseph `` US
2 Abraham. `` UK
3 g.wood '' Zambia
4 Messi. '' France
5 Ronaldo. '' Namibia
6 Pogba. '' Holand.
bookings
booking_id | user_id | booking_date | tour_id
1 1 2022-01-01 1
2 1 2022-01-01 6
3 1 2022-05-01 2
4 3 2022-01-01 5
5 2 2022-04-01 5
6 2 2022-11-01 7
7 3 2022-12-01 2
8 6 2022-01-01 1
this is what i have tried
SELECT s.nationality AS Nationality,
COUNT(b.tourist_id) AS touristsCount,
MONTH(STR_TO_DATE(b.booked_date, '%d-%m-%Y')) AS `MonthNumber`
FROM bookings b, users s
WHERE s.user_id = b.tourist_id
AND YEAR(STR_TO_DATE(b.booked_date, '%d-%m-%Y')) = '2022'
GROUP BY Nationality,MonthNumber
order BY MonthNumber ASC
LIMIT 100
i need the results to be like
nationality | TouritIdCount | MonthNumber
US 2 01
UK 1 04
US 1 05
UK 1 11
ZAMBIA 1 12
Try this :
SELECT nationality, COUNT(booking_id) AS TouristIdCount, MONTH(booking_date) AS MonthNumber
FROM users u
JOIN bookings b ON u.user_id = b.user_id
WHERE YEAR(booking_date) = 2022
GROUP BY nationality, MonthNumber
ORDER BY TouristIdCount DESC, MonthNumber ASC
you can use
having COUNT(b.tourist_id) >= 2
You want to count bookings per month and tourist's nationality and then show only the top nationality (or nationalities) per month.
There are two very similar approaches:
Rank the nationalities' booking counts per month with RANK and only show the best ranked rows.
Select the top booking count per month and only show rows matching their top count.
The following query uses the second method. It shows one row per month and top booking nationality. Often there may be excatly one row for a month showing the one top booking nationality, but there may also be months where nationalities tie and share the same top booking count, in which case we see more than one row for a month.
select year, month, nationality, booking_count
from
(
select
year(b.booking_date) as year,
month(b.booking_date) as month,
u.nationality,
count(*) as booking_count,
max(count(*)) over (partition by year(b.booking_date), month(b.booking_date)) as months_max_booking_count
from bookings b
join users u on u.user_id = b.tourist_id
group by year(b.booking_date), month(b.booking_date), u.nationality
) ranked
where booking_count = months_max_booking_count
order by year, month, nationality;
As your own sample data doesn't contain any edge cases, here is some other sample data along with my query's result and an explanation. (In other words, this is what you should have shown in your request ideally.)
users
user_id
username
email
nationality
1
Joseph
joseph#mail.us
US
2
Mary
mary#mail.us
US
3
Abraham
abraham#mail.uk
UK
bookings
booking_id
user_id
booking_date
tour_id
1
1
2022-01-11
1
2
2
2022-01-11
1
3
3
2022-01-11
1
4
3
2022-01-22
2
5
1
2022-05-01
3
6
2
2022-05-01
3
7
1
2022-05-12
4
8
2
2022-05-12
4
9
3
2022-05-14
5
10
3
2022-05-20
6
11
3
2022-05-27
7
result
year
month
nationality
booking_count
2022
1
UK
2
2022
1
US
2
2022
5
US
4
In January there were two tours, but we are not interested in tours. We see four bookings, two by the Americans, two by the Britsh person. This is a tie, and we show two rows, one for UK and one for US with two bookings each.
In May there were five tours, but again, we are not interested in tours. There are seven bookings, four by the Americans, three by the Britsh person. So we only show US as the top country with four bookings here.

multiple selects with different where conditions and limits

I have a high scores table that is slightly more complicated because scores are tracked in rounds (round 1, round 2, round 3, etc.). Sample table:
scoreID
roundID
userID
score
1
1
2
25
2
1
3
12
3
1
4
14
4
1
5
6
5
2
2
39
6
2
3
23
7
2
4
13
8
2
5
26
There can be many more rounds, and many more users.
I would like to pull the top 3 user scores from each round. My select statement at the moment looks like this:
select `scores`.`score`, `users`.`username`, `scores`.`roundID`
FROM `scores`
INNER JOIN `users` on `users`.`user_id` = `scores`.`userID`
ORDER BY `scores`.`score` DESC LIMIT 3;
However, this returns a result like so:
score
username
roundID
39
joey
2
26
bubba
2
25
george
1
when what I want is the top 3 scores per round:
score
username
roundID
25
george
1
14
bubba
1
12
joey
1
39
george
2
26
homey
2
23
joey
2
How do I select the top 3 scores in each round so my result mirrors the table immediately above?
You would do this like:
select score, username, roundID
from (
select
score, userID, roundID,
rank() over (partition by roundID order by score desc) score_rank
from score
) ranked_scores
inner join users on users.user_id = ranked_scores.userID
where score_rank <= 3
order by roundID, score, username

how to generate student attendance percentage per course, when they have specific day in a week

hi guys i really newbie in sql, i need help to generate percentage of attendance, here is the table:
Table Schedule
Schedule_ID Course_ID Lecture_ID Start_Date End_Date Course_Days
1 1 11 2019-09-09 2019-12-08 2,4,6
2 3 4 2019-09-09 2019-12-08 3,4
3 4 13 2019-09-09 2019-12-08 2,5
4 5 28 2019-09-09 2019-12-08 3
5 2 56 2020-01-27 2020-04-26 2,4
6 7 1 2020-01-27 2020-04-26 4,5
7 1 11 2020-01-27 2020-04-26 2,4,6
8 7 22 2020-01-27 2020-04-26 2,3
9 8 56 2020-01-27 2020-04-26 5
10 3 37 2020-01-27 2020-04-26 5,6
Reference of days of week used in this data.
1: Sunday, 2:Monday, 3:Tuesday, 4:Wednesday, 5:Thursday, 6:Friday, 7:Saturday
Table course_attendance
ID STUDENT_ID SCHEDULE_ID ATTEND_DT
1 1 2 2019-09-10
2 1 2 2019-09-11
3 1 2 2019-09-17
4 1 2 2019-09-18
......
46 2 1 2019-12-02
47 2 1 2019-09-11
48 2 1 2019-09-18
49 2 1 2019-09-25
50 2 1 2019-10-09
51 2 1 2019-10-16
....
111 6 1 2019-09-23
112 6 1 2019-09-30
113 6 1 2019-10-07
114 6 1 2019-10-14
table student
ID NAME
1 Jonny
2 Cecilia
3 Frank
4 Jones
5 Don
6 Harry
i need to show up like this :
STUDENT_ID NAME Course_ID Attendance rate
1 Jonny 1 82%
2 Cecilia 1 30%
3 Frank 3 100%
4 Jones 2 100%
5 Don 2 25%
6 Harry 4 40%
EDIT this my last step to get percentage:
result:
with main as (
select ca.STUDENT_ID,
ca.SCHEDULE_ID,
s.COURSE_ID,
co.NAME as course_name,
st.NAME,
count(ca.ID) as total_attendance,
((CHAR_LENGTH(s.COURSE_DAYS) - CHAR_LENGTH(REPLACE(s.COURSE_DAYS , ',', '')) + 1) * 13) as attendance_needed
from univ.course_attendance ca
left join univ.schedule s on ca.SCHEDULE_ID = s.ID
left join univ.student st on ca.SCHEDULE_ID = st.ID
left join univ.course co on ca.SCHEDULE_ID = co.ID
group by ca.STUDENT_ID, ca.SCHEDULE_ID
)
select *,total_attendance/attendance_needed as attendance_percentage
from main
order by 1,2;
This can be done following three steps.
Step 1: Calculate the total number of days a particular course of a schedule has. It's a good thing the start_date is always on Monday and the end_date is always on Sunday, which makes the week complete and saves some trouble. By calculating the total number of weeks a course go through and the number of days a week has for that course, we can get the total number of days a particular course of a schedule has.
Step 2:Calculate the total number of days a student for a schedule. This is done fairly easily. Note: As the majority part of the table has been skipped and the OP has yet to provide the complete data set, I could only have 14 existing rows provided.
Step 3: Calculate the percentage for the attendance using the result from the above two steps and get other required columns.
Here is the complete statement I wrote and tested in workbench:
select t2.student_id as student_id,`name`,course_id, (t2.total_attendance/t1.total_course_days)*100 as attendance_rate
from (select schedule_id,course_id,
length(replace(course_days,',',''))*(week(end_date)-week(start_date)) as total_course_days
from Schedule) t1
JOIN
(select count(attend_dt) as total_attendance,student_id,schedule_id
from course_attendance group by student_id, schedule_id) t2
ON t1.schedule_id=t2.schedule_id
JOIN
student s
ON t2.student_id=s.id;
Here is the result set ( the attendance_rate is not nice due to the abridged course_attendance table):
student_id, name, course_id, attendance_rate
2, Cecilia, 1, 15.3846
6, Harry, 1, 10.2564
1, Jonny, 3, 15.3846

MYSQL: Select from table A, based on seen date of user in Table B

OK I have three tables RegionName(Key, Name), Players(Key, Name, Seen), and regionplayers(key, regionkey, playerkey)
there is more to each table but it isn't needed so to make this easier i have only included what is needed.
I have regions, and a player can be added to a region, a region may have many players, and players can be on many regions. there are 1680 regions, 900ish players and about 3500 entries in the table linking them together.
I want to be able to find regions, where none of the players have been seen in 8+ days.
what I have atm is:
SELECT RegionName.*, RegionPlayer.*, Players.*
FROM RegionName
JOIN RegionPlayer
ON RegionPlayer.Regionkey= RegionName.Key
JOIN Players
ON Players.Key = RegionPlayer.Playerkey
WHERE
( Seen <= (NOW() - INTERVAL 8 DAY ) ) )
AND RegionName.Perent = 'none'
ORDER BY `RegionName`.`Name` ASC,
Players.Seen DESC
currently I get all the regions where people who have not been seen for 8+ days, so if a region has 1 player who hasn't been seen, it is returned, but I only want regions where everyone has been away for 8+days.
Here is a sort of sampling if the data for each of the tables, this was done by me just now. because its just easier then trying to pull enough data that makes the point, and should give the results I want.
RegionName
key Name
1 regionone
2 regiontwo
3 regionthree
4 regionfouor
5 regionfive
Players
Key Name Seen
1 jack 2014-03-21 12:43:46
2 joe 2014-03-26 12:43:46
3 bob 2014-03-20 12:43:46
4 bill 2014-03-19 12:43:46
5 dave 2014-03-17 12:43:46
6 tina 2014-03-28 12:43:46
7 tony 2014-03-29 12:43:46
8 george 2014-03-15 12:43:46
9 sam 2014-03-18 12:43:46
10 frank 2014-03-18 12:43:46
RegionPlayer
key Regionkey PlayerKey
1 1 1
2 1 4
3 1 5
4 2 1
5 2 4
6 2 2
7 3 6
8 3 1
9 3 7
10 4 1
11 4 8
12 4 7
13 4 5
14 5 3
So I should based on this data get back regions regionone, & regionfive.
SELECT RegionName.*, RegionPlayer.*, Players.*
FROM RegionName
JOIN RegionPlayer
ON RegionPlayer.Regionkey= RegionName.Key
JOIN Players
ON Players.Key = RegionPlayer.Playerkey
WHERE RegionName.Perent = 'none'
GROUP BY RegionName.Name
HAVING
SUM( Seen > (NOW() - INTERVAL 8 DAY ) ) =0
ORDER BY `RegionName`.`Name` ASC,
Players.Seen DESC

complex sql query in sql server 2008

I have 4 major tables in my database.
Season --> seasonID
Trials --> trialID
Competition --> CID,name
Camps --> campID,DivisionID(FK)
Divisions ---> DivisionID
Contestants --->ContestantID
Now a contestant belongs to / are members of a divisions.
Then a division belongs to a camp.
All this leads to my Performance table.
PERFORMANCE TABLE
SeasonID|TrialID|CampID|DivID|CompetionID|CtestantID|Score1 |Score2 |Total
1 1 1 1 1 1 20 20 40
1 1 1 1 2 1 20 15 30
1 2 1 1 1 2 10 5 15
1 2 1 1 2 2 5 5 10
1 2 1 1 1 1 10 30 40
1 2 1 1 2 1 20 10 30
How can I query this performance table to give me the competition name, total score and rank (ranking over total score) of each contestant in each competition by trials and by seasons?
Example:
In season 1 and trial 2 I want to have:
SeasonID| TrialID | ContestantID| Competition | TotalScore | Rank
1 2 1 1 40 1
1 2 2 1 15 2
1 2 1 2 30 1
1 2 2 2 10 2
How do I go about this? I have tried table variables, pivot and joins but I can only rank by competitions, but I don't how to aggregate the results to get the result above!
I'm not exactly sure how you calculated your desired results. I think this is what you are after but, if so, the TotalScore in the desired results of your question should be 10 for the last record, not 20.
SELECT SeasonID, TrialID, ContestantID, CompetitionID, Total,
DENSE_RANK() OVER(PARTITION BY CompetitionId ORDER BY Total DESC) AS [Rank]
FROM PerformanceTable