I have a table of users,subscription packages and various user subscriptions.
I need to fetch a sum of all subscription cost and display the latest/last subscription. The latest subscription is the subscription
with the highest subscription_id. How can I write my query? My tables are listed as below.
Users table
user_id name
1 John
2 Jane
3 Matthew
Subscription Packages table
package_id package_name
1 Basic
2 Advanced
3 Premium
User Subscriptions
subscription_id user_id package_id subscription_cost date
1 1 1 2 2014-04-01
2 2 1 2 2014-04-01
3 3 1 2 2014-04-01
4 1 1 2 2014-05-01
5 1 2 3.5 2014-06-01
6 2 2 3.5 2014-06-01
7 2 2 3.5 2014-07-01
8 1 3 5 2014-07-01
9 3 2 5 2014-07-01
10 2 2 3.5 2014-08-01
11 1 1 2 2014-08-01
My results should be like so
name total_costs latest_package
John 14.5 Basic
Jane 12.5 Advanced
Matthew 7 Premium
Because you need to do an aggregation anyway, I would go for the group_concat()/substring_index() trick:
select u.user_id, u.name, sum(subscription_cost) as total_costs,
substring_index(group_concat(p.package_name order by us.date desc), ',', 1) as latest_package
from usersubscriptions us join
users u
on us.user_id = u.user_id join
packages p
on us.package_id = p.package_id
group by u.user_id;
This assumes that no package names have commas. It is also subject to default limits on the length of the result of group_concat() -- but this method often works in practice.
Related
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
Whats the best way to check if different groups of rows in a table with the same GroupID such as different teams have a SINGLE captain? Captain Identifier for example could be '10', so its crucial that it goes through multiple records with the same groupID and checks to see if theres ONLY ONE record with the positionID as '10'. I need it to do it for all teams, i.e all groupID's
-------------------------------------------------
ID | Group ID | Name | Position|
-------------------------------------------------
1 1 John 3
2 1 jim 3
3 1 Hahn 4
4 1 Mary 4
5 1 Moe 4
6 1 Charlie 10
7 2 taylor 4
8 2 Geoff 4
9 2 adam 4
10 2 cam 10
11 3 sharon 2
12 3 tony 4
13 3 steve 3
14 3 eve 4
15 3 gwen 10
--------------------------------
So what I need it to do is check that every groupID only had ONE 10 as the position.
Thanks in advance guys. Check out the image link at the bottom.
im using mysql btw
Sorry if this is badly described
If I understood you - I think you need something like :
select groupId, sum(case when positionID='10' then 1 else 0 end) as captains
from tbl_name
group by groupID
having captains = 1
am I close???
If I understood you correctly, you want an indication that will tell you whether the groupID had more then one captain.
So what you need is this:
select groupID,case when cnt = 1 then 1 else 0 end as IND_ONE_CAPTAIN from (
select groupID, sum(case when positionid = '10' then 1 else 0 end) as cnt
from players
group by groupID)
Now IND_ONE_CAPTAIN columns consist 1 or 0, 1 is for the group id only had 1 captain, and 0 is when they had more.
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
I have two tables, one of a list of competition results, and one with ELO ratings (based on previous competitions).
Fetching the list of competitors for an arbitrary competition is trivial enough, but I also need to get the most recent rating value for them.
score:
id | eventid | competitorid | position
1 1 1 1
2 1 2 2
3 1 3 3
4 2 2 1
5 2 3 2
6 3 1 1
7 3 3 2
8 3 2 3
rating:
id | competitorid | rating
1 1 1600
2 2 1500
3 3 1500
4 2 1600
5 3 1590
Expected output for a query against score.eventid = 3 would be
id | competitorid | position | rating
6 1 1 1600
7 3 2 1590
8 2 3 1600
At the moment my code looks like:
SELECT score.scoreID, score.competitorID, score.position,
rating.id, rating.rating
FROM score, rating
WHERE score.competitorid = rating.competitorid
AND score.eventid = 3
ORDER BY score.position
which gives an output of
id | competitorid | position | rating.id | rating
6 1 1 1 1600
7 3 2 2 1500
7 3 2 4 1590
8 2 3 3 1500
8 2 3 5 1600
basically it's showing the data from the score table for that correct event, but giving me a row for every rating available against that competitorID unfortunately I have no idea where to build in the DISTINCT statement or how to limit it to the most recent result.
MySQL noob, and managed DISTINCT statements, but not with joins. Unfortunately most previous questions seemed to deal with getting distinct results from a single table, which is not quite what I'm after. Thanks!
One way to get the rating is with a correlated subquery:
SELECT s.scoreID, s.eventID, s.competitorID, s.position,
(select r.rating
from rating r
where s.competitorID = r.competitorID
order by r.id desc
limit 1
) as rating
FROM score s
WHERE s.eventID = 3
ORDER BY s.position;
I'm not sure what ratingprid is, so this only includes the rating.
I need help with a sql statement.
table users:
user_id name
----------------------
1 joe
2 sam
5 tammy
6 jade
10 tony
table a1:
id user_id year approved
----------------------------------
1 5 2012 1
2 6 2012 0
3 6 2013 1
4 5 2013 1
5 10 2012 0
6 10 2013 0
I need to return all 5 user_id wither or not they have an entry in table a1 and I need fields: a1.id, users.user_id, users.name, a1.year, a1.approved from the join.
My attempt:
select a1.id, users.user_id, users.name, a1.year, a1.approved from users
LEFT JOIN a1 as a1 ON a1.user_id = users.user_id
Im stuck.
Thanks