create view table that calculate total values base on multiple column values - mysql

These are my example table
course table include
course_id | course name
1 | java
2 | .net
3 | php
4 | ruby and rails
Indian_student table include
course_id | no.of student
2 | 10
3 | 30
Japan_student table include
course_id | no.of student
1 | 50
2 | 30
Chinese_student table include
course_id | no.of student
2 | 60
4 | 20
I want the output as
Course_id | in_stu | ja_stu | ch_stu | total
1 | 0 | 50 | 0 | 50
2 | 10 | 30 | 60 | 100
3 | 30 | 0 | 0 | 30
4 | 0 | 0 | 20 |20
But I only get the result
Course_id | in_stu | ja_stu | ch_stu | total
2 | 10 | 30 | 60 | 100
my view is
create view total_student as select
i.indian_stu as in_stu,
j.japan_stu as ja_stu,
c.chinese_stu as ch_stu,
main.course_id as course_id,
(i.indian_stu + j.japan_stu + c.chinese_stu) as total
from indian_student i, japan_student j,chinese_student c, course c
where i.course_id=main.course_id and j.course_id=main.course_id and c.course_id=main.course_id group by course_id;
can I get any advice please

You're using the 1990s-vintage method of joining tables together: comma-separated lists of tables. This is inadequate to your task. You need LEFT JOIN because the comma syntax is an INNER JOIN syntax. INNER JOIN omits rows without matches.
(Also, your sample query uses the c alias twice; that won't work. It also uses GROUP BY but I believe you want ORDER BY)
You want this:
select i.indian_stu as in_stu,
j.japan_stu as ja_stu,
x.chinese_stu as ch_stu,
main.course_id as course_id,
(i.indian_stu + j.japan_stu + c.chinese_stu) as total
from course c
left join indian_student i ON c.course_id = i.course_id
left join japan_student j ON c.course_id = j.course_id
left join chinese_student x on c.course_id = x.course_id
order by c.course_id
When you develop a view, first get the SELECT statement to work, then use it to create the view. That's easier than continually dropping and recreating the view.

Related

How to add default value on sum to have equal number of lines sum

I'm in front of a problem that regarding MySQL.
I have three tables in my Database :
Table gp
____________
id | name |
____________
1 | Le Mans|
2 | Toulon |
3 | Rennes |
Table player
____________
id | name |
____________
1 | Thibaut|
2 | Fred |
3 | Samir |
Table Records
_____________________________
id | gp_id | player_id | time
_____________________________
1 | 1 | 1 | 22
2 | 2 | 1 | 33
3 | 3 | 1 | 44
4 | 3 | 2 | 40
5 | 2 | 2 | 35
6 | 1 | 2 | 20
7 | 1 | 3 | 25
8 | 3 | 3 | 38
I want to get a sum of time for players that have at least one record on some specifics GP and to set a default time for the gp where they don't have a time
I have no idea how I can get that. Actually my SQL query get the values but I don't know how to set a default time for GP not finished by some players.
SELECT p.name, sum(time) as total_time
from records r
join gp g on r.gp_id = g.id
join player p on r.player_id = p.id
where gp.id in ( 1, 2, 3)
having count(distinct g.id) > 0
group by r.player_id
For example for this query I get these values :
name | total_time
_________________
Thibaut | 99
Fred | 95
Samir | 63
But I want a default time to 99 if there is no time for a player in one GP, so in my case Samir should have 63+99 => 162.
But I have no idea how to do that, and I don't know if it's possible
Thanks in advance guys !
Use LEFT JOIN to get a null value if there's no match, and IFNULL() to supply a default value in place of NULL.
Use a CROSS JOIN with gp to specify all the games that should be considered.
SELECT p.name, sum(IFNULL(time, 99)) as total_time
from player p
cross join gp
left join records r on r.player_id = p.id AND r.gp_id = gp.id
WHERE gp.id IN (1, 2, 3)
group by p.id
having count(distinct r.gp_id) > 0
DEMO

How can I not take in consideration values join without record on the db

I'm in front of a "minor" problem taht looks easy but I didn't suceed to resolve it.
I have three tables in my Database :
Table gp
____________
id | name |
____________
1 | Le Mans|
2 | Toulon |
3 | Rennes |
Table player
____________
id | name |
____________
1 | Thibaut|
2 | Fred |
3 | Samir |
Table Records
_____________________________
id | gp_id | player_id | time
_____________________________
1 | 1 | 1 | 17860
2 | 2 | 1 | 11311
3 | 3 | 1 | 33133
4 | 3 | 2 | 11113
5 | 2 | 2 | 44444
6 | 1 | 2 | 13131
7 | 1 | 3 | 11111
8 | 3 | 3 | 21112
I want to get a sum of time for players that have a record on every gp ( so in my case, just players Thibaut and Fred have a record on the 3 gp ( Samir has just a record on two gp ) ).
I have no idea how I can get that, of course this SQL query is retrieving a sum but from this query I want to escape the guys that don't have a record on every GPs, but I'm blocked at that point ...
SELECT p.name, sum(time)
from records r
join gp g on r.gp_id = g.id
join player p on r.player_id = p.id
group by r.player_id
Thanks in advance guys !
You could use having count to exclude the records that don't have a record on every GPs.
Try:
select p.name,
sum(`time`) as tot_sum
from records r
inner join player p on r.player_id=p.id
inner join gp g on g.id=r.gp_id
group by p.name
having count(distinct gp_id) = (select count(distinct id) from gp)
https://dbfiddle.uk/t8QwSFDY
having count(distinct gp_id) = (select count(distinct id) from gp) will match only the records in the record table that have a record on every gp.

MySQL Select from Multiple Tables and most recent record

I'm having issues with a select query and can't quite figure out how to fix. I have two tables:
TABLE_students
|--------|------------|--------|
| STU_ID | EMAIL | NAME |
|--------|------------|--------|
| 1 | a#e.com | Bob |
| 2 | b#e.com | Joe |
| 3 | c#e.com | Tim |
--------------------------------
TABLE_scores
|--------|------------|-------------|--------|
| SRE_ID | STU_ID | DATE | SCORE |
|--------|------------|-------------|--------|
| 91 | 2 | 2018-04-03 | 78 |
| 92 | 2 | 2018-04-06 | 89 |
| 93 | 3 | 2018-04-03 | 67 |
| 94 | 3 | 2018-04-06 | 72 |
| 95 | 3 | 2018-04-07 | 81 |
----------------------------------------------
I'm trying to select data from both tables but have a few requirements. I need to select the student even if they don't have a score in the scores table. I also only only want the latest scores record.
The query below only returns those students that have a score and it also duplicates returns a total of 5 rows (since there are five scores). What I want is for the query to return three rows (one for each student) and their latest score value (or NULL if they don't have a score):
SELECT students.NAME, scores.SCORE FROM TABLE_students as students, TABLE_scores AS scores WHERE students.STU_ID = scores.STU_ID;
I'm having difficulty figuring out how to pull all students regardless of whether they have a score and how to pull only the latest score if they do have one.
Thank you!
This is a variation of the greatest-n-per-group question, which is common on Stack Overflow.
I would do this with a couple of joins:
SELECT s.NAME, c1.DATE, c1.SCORE
FROM students AS s
LEFT JOIN scores AS c1 ON c1.STU_ID = s.STU_ID
LEFT JOIN scores AS c2 ON c2.STU_ID = s.STU_ID
AND (c2.DATE > c1.DATE OR c2.DATE = c1.DATE AND c2.SRE_ID > c1.SRE_ID)
WHERE c2.STU_ID IS NULL;
If c2.STU_ID is null, it means the LEFT JOIN matched no rows that have a greater date (or greater SRE_ID in case of a tie) than the row in c1. This means the row in c1 must be the most recent, because there is no other row that is more recent.
P.S.: Please learn the JOIN syntax, and avoid "comma-style" joins. JOIN has been standard since 1992.
P.P.S.: I removed the superfluous "TABLE_" prefix from your table names. You don't need to use the table name to remind yourself that it's a table! :-)
You could use correlated subquery:
SELECT *,
(SELECT score FROM TABLE_scores sc
WHERE sc.stu_id = s.stu_id ORDER BY DATE DESC LIMIT 1) AS score
FROM TABLE_students s

How to count users with where condition previous row

please help me i have no idea for this...
I have table like this (create_at YYYY-MM-DD). ID is auto increment
-----------------------------------------------------------------
| ID | id_user | activity | create_at |
-----------------------------------------------------------------
| 1 | 10 | A | 2017-10-11 |
| 2 | 52 | A | 2017-10-11 |
| 3 | 41 | A | 2017-10-12 |
| 4 | 52 | A | 2017-10-12 |
| 5 | 41 | B | 2017-10-12 |
| 6 | 52 | B | 2017-10-13 |
| 7 | 10 | B | 2017-10-14 |
-----------------------------------------------------------------
How to get count (mysql) user who doing activity "B" after activity "A" in sameday create_at.. In this case, the result is 1 (IDUser 41).. How can i do this in mysql? thankyou
We could use a semi-join or a correlated subquery.
we start like this, users that are doing activity B
SELECT t.id_user
FROM table_like_this t
WHERE t.activity = 'B'
we can match those rows to users that are doing activity A on the "same day" with JOIN operation back to the same table...
SELECT t.id_user
FROM table_like_this t
JOIN table_like_this r
ON r.id_user = t.id_user
AND r.create_at = t.create_at
AND r.activity = 'A'
WHERE t.activity = 'B'
As far as whether activity B is occurring "after" activity A, I don't see any information in the table that can tell us that (we can't tell what time each activity A and B occurred, and can't determine which one was "after" the other.)
For testing, we can include other columns in the SELECT list, to verify which rows from t and r are being returned, if the matching is being done properly.
Once we are satisfied, we can replace the SELECT list, to get a count of distinct id_user
SELECT COUNT(DISTINCT t.id_user)
FROM ...
Note that this will collapse occurrences of id_user that performed activity A and B on several different days so that the id_user will be counted only once.
If we want to count the number of days for each id_user, and include each of those days in the count, the query would need to be changed.

Sql SUM over products of grouped elements

I have the following data structure:
Table 1(groups):
ID | Group
=============
1 | Sample
2 | Data
Table 2(items):
ID | GroupID | Cost | Amount
==============================
1 | 1 | 1 | 12
2 | 1 | 7 | 15
3 | 1 | 3 | 8
4 | 2 | 2 | 12
And would like the following (query) results:
groups.ID | groups.Name | total
1 | Sample | 141
2 | Data | 24
total is the sum over the products of cost and amount of all items in the group i.e. for group 1: 1*12+7*15+3*8=141
Im guessing I have to something with
SELECT g.ID, g.Group, SUM(Products)
FROM groups AS g, items AS i
WHERE g.ID=i.GroupID
GROUP BY i.GroupID
But don't know what exactly.
Doing iit in clientsoftware with loops is no problem, but I am curious (and certain) that this can be done in (my)Sql
SELECT g.ID as ID, g.Group as Name, SUM(i.Cost * i.Amount) as total
FROM groups g
INNER JOIN items i ON i.GroupID = g.ID
GROUP BY g.Group, g.ID
Having a field named "Group" is quite a bad idea in SQL (reserved keyword)