MySQL Query to get student grades AND class average - mysql

I am fairly new to the world of SQL and am finding the syntax a tad bit awkward to work with while I try to understand how joins and such work. I am practicing by building a small web app that lets you pick a date and possibly a name of a student (if none is defined then all students are shown). My idea is that basically multiple tables (one per student) will be generated off of a given query and it would show the student's name and other related info, along with this it also will show the average grade of all the students along side that specific students information. However, I am not sure how to actually make a query that will return all the students, those with and without grades on a given date, alongside the overall average of that test/quiz on said date.
The tables I am working with are student which has a student_id, name and sex. An Event table that has an event_id, type (test or quiz) and a date. And finally a score table that has an event_id, student_id and a score.
Essentially the resulting query would return a table with these columns.
| student_id | Name | Date | Type | Grade | Class Avg |
every row is a unique student, the date the given test or quiz was taken on, the grade they got (if they took test/quiz, otherwise it's NULL) and then the class avg for that test/quiz. I know how to get everything up to the class average. I'm not even sure if it is or isn't possible without doing 2 queries or to calculate it myself while rendering the webpage.

Related

Using Lookup and getting a count from each Dataset

I have two datasets and I'm using Lookup to get one result, but the total is only from one dataset. I've tried and tried, but I'm having no luck.
First Dataset is called MedCond
This is the Data:
Drug_Name
Start_Date
Stop_Date
InmateID
Drug_Indication
Created
ID
Second Dataset is called ProblemList
This is the Data:
Medical_Condition
Inmate_ID
Created
ID
Drug Indication and Medical Condition are the same. I want to get a combined total of both.
This only gives me the count of the Drug Indications (which I have them grouped on) =Count(Lookup(Fields!Drug_Indication.Value,Fields!Medical_Condition.Value,Fields!Medical_Condition.Value, "ProblemList"))
I feel like I've tried everything under the sun. I'm extremely exasperated. I'm trying to get a total of each of the conditions/Indications that come from each dataset. For instance, One condition/Indication might be Addiction. There may be four addictions in from the Drug_Indication in the MedCon dataset and five addictions from the Medical_Condition in the ProblemList. I want to see Addictions 9 on the table and so and so forth for each Drug Indication/Medical Condition.
Thanks in advance for your help! Save my sanity. :) I'm sure it's probably something simple?
Tara
Thank you. I've tried using the Inmate_ID and InmateID as the key to join, but I still end up with only one of counts of either Medical_Condition or Drug_Indication.
As an example, there might be 10 addictions in one and 15 addictions in the other. I need them to be grouped under the title addiction (and whatever other titles there might be) with the total being 25.
It would look something like this.
Example Look
Something like this is close, but the counts aren't quite right.
=Count(Lookup(Fields!InmateID.Value, Fields!Inmate_ID.Value, Fields!Medical_Condition.Value, "ProblemList")) + Count(Fields!Drug_Indication.Value)
Maybe it's the way I'm grouping? How do you group on a combination of values such as Medical_condition and Drug_Indication?
Thanks again!
Tara
I think you used the Lookup() wrong. When I look at your two datasets (for me) the key to join the two datasets would be Inmate_ID.
=Lookup(Fields!InmateID.Value, Fields!Inmae_ID.Value, Fields!Medical_Condition.Value, "SecondDatasetName")
This would result in a table like this (The last column comes form the lookup above):
Drug_Name | Start_Date | Stop_Date | InmateID | Drug_Indication | Created | ID | Medical_Condition
Now you can just get the total per column:
Drug_Name | Start_Date | Stop_Date | InmateID | Drug_Indication | Created | ID | Medical_Condition
Total1 Total2
To sum Total1 and Total2 you can add a new tablix and reference to the textbox totals like this:
=ReportItems!Total1TextboxName.Value + ReportItems!Total2TextboxName.Value

Relational Database Logic

I'm fairly new to php / mysql programming and I'm having a hard time figuring out the logic for a relational database that I'm trying to build. Here's the problem:
I have different leaders who will be in charge of a store anytime between 9am and 9pm.
A customer who has visited the store can rate their experience on a scale of 1 to 5.
I'm building a site that will allow me to store the shifts that a leader worked as seen below.
When I hit submit, the site would take the data leaderName:"George", shiftTimeArray: 11am, 1pm, 6pm (from the example in the picture) and the shiftDate and send them to an SQL database.
Later, I want to be able to get the average score for a person by sending a query to mysql, retrieving all of the scores that that leader received and averaging them together. I know the code to build the forms and to perform the search. However, I'm having a hard time coming up with the logic for the tables that will relate the data. Currently, I have a mysql table called responses that contains the following fields,
leader_id
shift_date // contains the date that the leader worked
shift_time // contains the time that the leader worked
visit_date // contains the date that the survey/score was given
visit_time // contains the time that the survey/score was given
score // contains the actual score of the survey (1-5)
I enter the shifts that the leader works at the beginning of the week and then enter the survey scores in as they come in during the week.
So Here's the Question: What mysql tables and fields should I create to relate this data so that I can query a leader's name and get the average score from all of their surveys?
You want tables like:
Leader (leader_id, name, etc)
Shift (leader_id, shift_date, shift_time)
SurveyResult (visit_date, visit_time, score)
Note: omitted the surrogate primary keys for Shift and SurveyResult that I would probably include.
To query you join shifts and surveys group on leader and taking the average then jon that back to leader for a name.
The query might be something like (but I haven;t actually built it in MySQL to verify syntax)
SELECT name
,AverageScore
FROM Leader a
INNER JOIN (
SELECT leader_id
, AVG(score) AverageScore
FROM Shift
INNER JOIN
SurveyResult ON shift_date = visit_date
AND shift_time = visit_time --depends on how you are recording time what this really needs to be
GROUP BY leader ID
) b ON a.leader_id = b.leader_id
I would do the following structure:
leaders
id
name
leaders_timetabke (can be multiple per leader)
id,
leader_id
shift_datetime (I assume it stores date and hour here, minutes and seconds are always 0
survey_scores
id,
visit_datetime
score
SELECT l.id, l.name, AVG(s.score) FROM leaders l
INNER JOIN leaders_timetable lt ON lt.leader_id = l.id
INNER JOIN survey_scores s ON lt.shift_datetime=DATE_FORMAT('Y-m-d H:00:00', s.visit_datetime)
GROUP BY l.id
DATE_FORMAT here helps to cut hours and minutes from visit_datetime so that it could be matched against shift_datetime. This is MYSQL function, so if you use something else you'll need to use different function
Say you have a 'leader' who has 5 survey rows with scores 1, 2, 3, 4 and 5.
if you select all surveys from this leader, sum the survey scores and divide them by 5 (the total amount of surveys that this leader has). You will have the average, in this case 3.
(1 + 2 + 3 + 4 + 5) / 5 = 3
You wouldn't need to create any more tables or fields, you have what you need.

MySQL - Difficulty getting sum with other data between two tables

I am using the Invision Power Board suite for purchases, but they do not provide a way to get the total a customer has paid. So I am attempting to write an SQL Query for this information. My knowledge of SQL is extremely limited, so ... I may be taking the wrong approach.
From what I have gathered, the information I need is on two tables, but the way it outputs is not useful to me since it outputs every individual purchase, with only the member's unique ID (relatively useless in bulk operations and examination)
I have so far gotten to this point...
SELECT member_id, email, name,
SUM(ibf_nexus_invoices.i_total) as SUM_TOTAL
FROM ibf_members
RIGHT JOIN ibf_nexus_invoices ON ibf_members.member_id = ibf_nexus_invoices.i_member
WHERE ibf_nexus_invoices.I_status = "paid";
This takes everything from the members table and the invoices table, and outputs it like this..
------------------------------------------------------------
member_id | email | name | SUM_TOTAL |
------------------------------------------------------------
4 | email#domain.com | "Derek" | 184.22 |
------------------------------------------------------------
At first glance, this looks like what I want. But it only returns one person, not all of the people in the member's list. Is anyone versed enough with SQL to help steer me in the right direction?
You need to add
GROUP BY member_id
to the end of the query to get a row per person. Otherwise, aggregate functions like SUM() combine all the rows in the result.

ORDER BY proirity with specific value

I have a table with a column named role and values are as follow:
Scientific staff
PostDocs
Supporting staff
PNUT
Visiting researchers
Secretary
Ph.D. students
Students
Other
I want to use ORDER BY in such a way that Scientific staff comes first. At the moment when I do a query like this, the fields which are Ph.D. students will be returned first (Well because at the moment no row in database has a field with Other in it). Is there a way to achive this using mysql only or should I modify the returned values manually? If so, can you please tell me how?
SELECT * FROM members ORDER BY role
You can do it without an additional table and join, just do:
SELECT * FROM members
ORDER BY
CASE role
WHEN 'Scientific staff' THEN 1
WHEN 'PostDocs' THEN 2
WHEN 'Supporting staff' THEN 5
WHEN 'PNUT' THEN 6
WHEN 'Visiting researchers' THEN 4
WHEN 'Secretary' THEN 3
WHEN 'Ph.D. students' THEN 8
WHEN 'Students' THEN 7
WHEN 'Other' THEN 9
ELSE 10
END
As it is currently implemented, you cannot order by in such a way that Scientific Staff is first, because doing an Oder By sorts it in order of the item in question (in your case, alphabetically it appears by role).
Now, the easy solution to this is to build out a sort priority table with those values in it, assign a numeric priority, then sort by the priority. Let me explain that a little better because it can be confusing:
You make a second table, listing each of these roles, and in a second column give those roles a priority that they will be displayed by.
TABLE:
Role | Priority
Scientific Staff | 1
Ph.D Students | 2
Other | 3
(etc)
You can then do something like this (pseudo-MySQL):
select members.role from members
inner join priority
on members.role = priority.role
order by priority.priority
that will give you the role field from the members table, ordered by the priority you set on the priority table. Since it is an inner join, anyone without a role will not display.

MySQL get only the row with the highest ID of a query

Hello Stackoverflow community,
This is my first post here, so I apologize for my bad English! :)
If you don't want to read everything, the Questions are marked like this.
The title is a little misleading, but I didn't know how to explain it in a better way, but the detailed explanation should let you understand:
I have a big log table (about 500000 rows at this time), where a game server logs many actions that occur in the game. I want to extract some specific log rows the most efficient way.
I can't change the logging system of the game server, if I could I would change it to many more log tables, to create more compact logs. (because executing queries on that table takes it's time..)
Now my problem is, that I want to get the last log row of a specific type and from a specific player id to get the players last action, and I don't know how to do that in an efficient way.
Example:
SELECT * FROM log WHERE logType = "PLAYER" AND playerID = [playerID] ORDER BY time DESC LIMIT 1
Then the output on the website would be:
You last action was [the human readable action and additional information].
MySQL profiling now tells me that sorting of the results takes the most amount of time.
Now my question is: Is it possible to get only the last row of a specific player id and type?
I guess it could be done with the ID, cause it has auto_increment. So is it possible to get the row with the highest ID, a specific type and a specific player id?
The table structure:
ID(int) | logType(varchar) | time(datetime) | playerID(int) | positionX(int) | positionY(int) | actionID(int) | action(varchar) | hints(varchar) | ip(varchar) | itemNumber(int)
Explaination:
ID: the unique id of the logged action
logType: the type of the logged action (Example: "PLAYER" or "ITEM")
time: the time the action occured
playerID: the id of the player (or other id's related to that type)
positionX: X position in the game
positionY: Y position in the game
actionID: an id in relation to the action (Example: If the log action is "KILLED_BY_PLAYER", then the player id of the other player who killed the player)
action: the action that is logged (Example: KILLED_BY_PLAYER)
hints: Some useful hints like the name of the player
ip: The IP of the player
itemNumber: The number of the Item, if an Item is involved, else NULL
Thanks for your help. :)
to get the highest id:
select max(id) from table;
the others you could put a where clause in the select statement.
You should be able to use your query where you sort on time with LIMIT 1. If your sort on the column time is slow, you must make sure the indexes are optimized (run explain on your query). You will need indexes on both logtype, player_id and time. Even with 500 000 rows this shouldn't be a problem...