SQL merge a table on itself [duplicate] - mysql

WEEK STUDENT CLASS TEST SCORE
1 1 A 1 93
1 1 A 2 97
1 1 B 1 72
1 1 B 2 68
1 1 C 1 93
1 1 C 2 51
1 1 H 1 19
1 2 A 1 88
1 2 A 2 56
1 2 B 1 53
1 2 B 2 79
1 2 C 1 69
1 2 C 2 90
1 2 H 1 61
1 3 A 1 74
1 3 A 2 50
1 3 B 1 76
1 3 B 2 97
1 3 C 1 55
1 3 C 2 63
1 3 H 1 63
2 1 A 1 59
2 1 A 2 68
2 1 B 1 77
2 1 B 2 80
2 1 C 1 52
2 1 C 2 94
2 1 H 1 74
2 2 A 1 64
2 2 A 2 74
2 2 B 1 92
2 2 B 2 98
2 2 C 1 89
2 2 C 2 84
2 2 H 1 54
2 3 A 1 51
2 3 A 2 82
2 3 B 1 86
2 3 B 2 51
2 3 C 1 90
2 3 C 2 72
2 3 H 1 86
I wish to group by STUDENT and WEEK and find the MAXIMUM(SCORE) value when TEST = 1. Then I wish to add the corresponding rows for CLASS and also the score for TEST = 2 based to get this:
WEEK STUDENT CLASS TEST1 TEST2
1 1 A 93 97
2 1 A 88 56
1 2 B 76 97
2 2 B 77 80
1 3 B 92 98
2 3 C 90 72
This is what I try but in SQL I am no able to SELECT columns which I don't group by
SELECT STUDENT, WEEK, CLASS, MAX(SCORE)
FROM DATA
WHERE TEST = 1
GROUP BY (STUDENT, WEEK)
but I do not find a solution that works.

Write a subquery that gets the highest score for each week and student on test 1. Join that with the table to get the rest of the row for that same score.
Then join that with the table again to get the row for the same student, week, and class, but with test = 2.
SELECT t1.week, t1.student, t1.class, t1.score AS test1, t3.score AS test2
FROM yourTable AS t1
JOIN (
SELECT week, student, MAX(score) AS score
FROM yourTable
WHERE test = 1
GROUP BY week, student
) AS t2 ON t1.week = t2.week AND t1.student = t2.student AND t1.score = t2.score
JOIN yourTable AS t3 ON t3.week = t1.week AND t3.student = t1.student AND t3.class = t1.class
WHERE t1.test = 1 AND t3.test = 2
ORDER BY student, week
DEMO

Related

MySQL: select sum of column having specific values

What I'm trying to do is to select a specific amount of tickets (max 2) and every person that has the sum of the number of tickets less of 3 and the valid field has to be != 'e'
I have this table:
ID
id_person
nr_tickets
valid
1
220
1
s
2
220
1
s
3
330
2
s
4
330
1
e
5
331
1
s
6
220
2
s
7
441
1
s
8
442
2
s
9
443
1
s
10
444
1
s
11
445
2
s
Here is what I did:
SELECT m.id, m.id_person, m.nr_tickets, m.valid
FROM table m
JOIN table m1 ON m1.id <= m.id
WHERE m.nr_tickets > 0
GROUP BY m.id
HAVING SUM(case when m.valid != 'e' then m1.nr_tickets end) <= 10
This query gives me
ID
id_person
nr_tickets
valid
1
220
1
s
2
220
1
s
3
330
2
s
5
331
1
s
6
220
2
s
7
441
1
s
8
442
2
s
As you can see the query it's almost right, the thing is that the person 220 in the results has the sum of the tickets is greater than 2.
What I'm trying to achieve is to bypass the ID 6, and to have instead the ID 9
select `id`,`id_person`, sum(`nr_tickets`) as `nr_tickets`, `valid`
from `test`
group by `id_person`
having sum(`nr_tickets`) < 3 and `valid`!="e"
Output:
id id_person nr_tickets valid
5 331 1 s
7 441 1 s
8 442 2 s
9 443 1 s
10 444 1 s
11 445 2 s

Mysql rank with join table, result not true

I have 2 table name table 'hasil' and table 'kat_soal' to join and give rank on each 'KatID' field on 'hasil' table..
here is my hasil table :
HasilID KatID UserID JBenar JSalah Nilai
15 1 1000 2 1 66.66666666666666
16 3 1000 2 0 100
17 1 1001 1 2 33.33333333333333
18 3 1001 1 1 50
19 1 1002 3 0 90
20 3 1002 2 0 80
and there is my kat_soal table
KatID Kategori Lama
1 IPA 30
2 IPS 30
3 Matematika 30
4 Bahasa Indonesia 20
5 Bahasa Inggris 20
this my query generate rank:
SELECT a.KatID,a.UserID,b.Kategori,c.Nama,a.JBenar,a.JSalah,ROUND(a.Nilai,2) as Nilai,
FIND_IN_SET( a.Nilai, l.list) AS rank
from hasil a
JOIN kat_soal b
ON a.KatID = b.KatID
JOIN datauser c
ON a.UserID=c.UserID
CROSS JOIN
(SELECT GROUP_CONCAT( a2.Nilai ORDER BY a2.Nilai DESC ) as list
FROM hasil a2) l
WHERE a.KatID='1'
ORDER BY a.Nilai DESC;
my result
//FOR KatID=1
KatID UserID Kategori Nama JBenar JSalah Nilai rank
1 1002 IPA ratam 3 0 90.00 2
1 1000 IPA Tarsan 2 1 66.67 4
1 1001 IPA wisnu 1 2 33.33 6
//FOR KatID=3
3 1000 Matematika Tarsan 2 0 100.00 1
3 1002 Matematika ratam 2 0 80.00 3
3 1001 Matematika wisnu 1 1 50.00 5
My Expected Result
//FOR KatID=1
KatID UserID Kategori Nama JBenar JSalah Nilai rank
1 1002 IPA ratam 3 0 90.00 1
1 1000 IPA Tarsan 2 1 66.67 2
1 1001 IPA wisnu 1 2 33.33 3
//FOR KatID=3
3 1000 Matematika Tarsan 2 0 100.00 1
3 1002 Matematika ratam 2 0 80.00 2
3 1001 Matematika wisnu 1 1 50.00 3
anyone can help me ?
Good example to solve the issue is by looking at: http://www.fromdual.com/ranking-mysql-results .
You are making this a bit complicated: First You take the value, making the value a string, then "finding position in string".
From the example it should be completely ok if it is done as (untested):
SET #rank=0;
SELECT a.KatID,a.UserID,b.Kategori,c.Nama,a.JBenar,a.JSalah,ROUND(a.Nilai,2) as Nilai,
#rank:=#rank+1 AS rank
from hasil a
JOIN kat_soal b
ON a.KatID = b.KatID
JOIN datauser c
ON a.UserID=c.UserID
WHERE a.KatID='1'
ORDER BY rank;
EDIT: Changed ordering - You are expecting to by ordered by rank in the final.
Below is the script without using table datauser for any1 to test:
SET #rank=0;
SELECT a.KatID,a.UserID,b.Kategori,a.JBenar,a.JSalah,ROUND(a.Nilai,2) as Nilai,
#rank:=#rank+1 AS rank
from hasil a
JOIN kat_soal b
ON a.KatID = b.KatID
WHERE a.KatID='1'
ORDER BY rank;

SQL: Split Dataset into two columns

I have a table like this:
id c_id time value
1 4 1 12
2 4 2 5
3 4 3 6
4 4 4 48
5 4 5 1
6 4 6 121
7 5 1 121
8 5 2 321
9 5 3 2
10 5 4 1
11 5 5 54
12 5 6 4546
13 5 7 78
14 5 8 784
15 5 9 1
Now I want a table like this with a SELECT command:
time1 value1 time2 value2
1 12 1 121
2 5 2 321
3 6 3 2
4 48 4 1
5 1 5 54
6 121 6 4546
0 0 7 78
0 0 8 784
0 0 9 1
time1 and value1 is from the data with c_id=4,
time2 and value2 is from the data with c_id=5
Is it possible to create a SELECT command to do that?
I hope you can help
Yiu can use an inner join
select a.time as time1, a.value as value1, b.time as time2, b.value as value2
from my_table as a
inner join my_table as b on a.time = b.time
and a.c_id= 4
and b.c_id= 5;

list all students who have written atmost one exam per day

I have 3 tables likes Student,Subject,and Midterm tables.
Student table contains
studid Firstname lastname Class
1 A R 12A
2 B S 12A
3 C T 12A
4 D U 12A
5 E V 12B
SUBJECT table contains
subid subname
1 maths
2 science
3 english
MIDTERM table contains
studid subid marks examdate
1 1 100 2014-09-24
1 2 92 2014-09-25
1 2 92 2014-09-26
2 1 74 2014-09-24
2 2 78 2014-09-26
2 3 73 2014-09-26
3 1 90 2014-09-24
3 2 84 2014-09-25
3 2 92 2014-09-25
5 1 87 2014-09-24
4 2 79 2014-09-24
4 3 90 2014-09-26
select * from Student
EXCEPT
--list of students with more than one subject per day
select A.* from Student A
join
(select studid, examdate, count(distinct subid)cnt group by studid, examdate from [Midterm]
)B
on A.Studid = B.Studid
and B.cnt >1

SQL many-to-many count sum

I have this table:
id_user id_user2
1 54
1 53
1 53
1 54
1 54
1 55
2 23
2 23
2 20
2 21
2 25
2 25
And i would like to count, how many each of id_user have relationship with id_user2. Output should be:
id_user id_user2 result
1 54 3
1 53 2
1 55 1
2 23 2
2 20 1
2 21 1
2 25 2
You have to use group by clause
select id_user,id_user2, count(1) as result
from userstab
group by id_user,id_user2
try this query
select id_user,id_user2,count(id_user2) as result
from TABLE_NAME group by id_user2