Assalammualaikum..
I have database like this:
name | subjects | score
B | math | 70
B | math | 80
B | scien | 90
A | math | 80
And I have query like this:
$query = mysqli_query($db,"SELECT name, subject, score
(
CASE subject WHEN #curSubject
THEN #curRow := #curRow +1
ELSE #curRow :=1 AND #curSubject:= subject END
) AS rank
FROM table GROUP BY name,score ORDER BY name, score desc");
If I Select on SQL output from that query just like this:
name | subjects | score | rank
B | math | 80 | 1
B | math | 70 | 2
B | scien | 90 | 1
A | math | 80 | 1
My problem is, when I will echo using looping php code like this:
while ($array = mysqli_fetch_array($query)){
echo $array['rank']'';
}
output:
rank | rank (not like this)
1 | 1
1 | 2
1 | 1
1 | 1
How can the value rank be echoed? Thank you
Wassalammualaikum..
Related
I have a table as below
ID_STUDENT | ID_CLASS | GRADE
-----------------------------
1 | 1 | 90
1 | 2 | 80
2 | 1 | 99
3 | 1 | 80
4 | 1 | 70
5 | 2 | 78
6 | 2 | 90
6 | 3 | 50
7 | 3 | 90
I need to then group, sort and order them and update the assigned rank :
ID_STUDENT | ID_CLASS | GRADE | RANK
------------------------------------
2 | 1 | 99 | 1
1 | 1 | 90 | 2
3 | 1 | 80 | 3
4 | 1 | 70 | 4
6 | 2 | 90 | 1
1 | 2 | 80 | 2
5 | 2 | 78 | 3
7 | 3 | 90 | 1
6 | 3 | 50 | 2
Can anyone help me to achieve this in mysql .
Below query will sorts the results group by ID_CLASS and in the descending order of GRADE columns.
Query
select `ID_STUDENT`, `ID_CLASS`, `GRADE`, (
case `ID_CLASS`
when #curA then #curRow := #curRow + 1
else #curRow := 1 and #curA := `ID_CLASS` end
) as `rank`
from `your_table_name` g,
(select #curRow := 0, #curA := '') r
order by `ID_CLASS`, `GRADE` desc;
We can use session variables here to simulate the rank. Note carefully that you are really after the rank, and not just the row number. The reason for this is that two or more students in a given class could be tied with the same grade. Your sample data did not include such an edge case, but the case is present in your problem. I chose to use the dense rank here, which means that if a class had give students with the following grades:
student | grade | dense rank
1 | 90 | 1
2 | 90 | 1
3 | 90 | 1
4 | 80 | 2
5 | 65 | 3
then a three-way tie for the highest grade would mean that all three students would be first, with the next highest student coming in at second. The alternative would be to use the rank, in which case the next highest student would have rank 4.
SET #dr = 1;
SET #id_class = NULL;
SET #grade = NULL;
SELECT
ID_STUDENT,
#dr:=CASE WHEN (#id_class = ID_CLASS AND #grade <> GRADE) THEN #dr + 1
WHEN (#id_class = ID_CLASS AND #grade = GRADE) THEN #dr
ELSE 1 END AS dr,
#id_class:=ID_CLASS AS ID_CLASS,
#grade:=GRADE AS GRADE
FROM yourTable
ORDER BY
ID_CLASS,
GRADE DESC;
Output:
Demo here:
Rextester
SELECT ID_STUDENT,ID_CLASS,GRADE,RANK
FROM
(
SELECT ID_STUDENT,ID_CLASS,GRADE,CASE WHEN #ID_CLASS=ID_CLASS THEN #RANK:= #RANK+1 ELSE #RANK :=1 END RANK,#ID_CLASS:=ID_CLASS
FROM STUDENT_TABLE,(SELECT #RANK :=0,#ID_CLASS:=1)Z ORDER BY ID_CLASS ASC,GRADE DESC
)ZZ;
You can try above query.
Here is SQLFiddle Demo
i have seem u r question and find out ans as per u r need.
i think help below query to find data proper format.
SELECT * FROM `temp_u` GROUP BY `ID_STUDENT` ORDER by `RANK` ASC
UPDATE youre_tbl t2
SET t2 .RANK= (SELECT *
FROM youre_tbl t
ORDER BY t.GRADE)
FROM t2
WHERE t2.ID = t.ID
You can get ordered result from this.
I have a table like this
+-------+-------+-------+-------+
| id | cid | grade |g_point|
+-------+-------+-------+-------+
| 1 | 10 | A+ | 1 |
| 2 | 10 | A+ | 1 |
| 3 | 10 | B | 3 |
| 4 | 11 | A | 2 |
| 5 | 11 | A+ | 1 |
| 6 | 12 | B | 3 |
the column g_point is the values associated to each grade. forexample A+ grade considers highest so I assign the value of A+ is one(highest starts from 1 to 10) and so on. These g_point values are constant. Now what I want to do is I want to show the maximum grade against each course and also if somehow there are only two entries of different grades I want to compare it with the g_point and choose whose value is lower because lower integer value means higher grade. the result should be like this and also sorted from top grade to lower.
+-------+-------+
| cid | grade |
+-------+-------+
| 10 | A+ |
| 11 | A+ |
| 12 | B |
I have tried this query
SELECT coursecodeID AS cid, (SELECT grade
FROM feedback
WHERE coursecodeID = cid
GROUP BY grade
ORDER BY COUNT(*) DESC LIMIT 0,1) AS g
FROM feedback
GROUP BY coursecodeID
but in this query I don't know how can I compare it with g_point value and also the courses is not showing in order(from highest grade to lowest).
NOTE: I want to choose the grade having the maximum number of occurrences per course id. For example here in this table course id 10 has 2 A+ grade so we'll consider A+ and if clash happens like one is A+ and the other is B+, then we'll have to compare it with the g_point
This works, but needs the 'g_point' to alse be returned.
SELECT cid,grade,MIN(g_point)
FROM grades
GROUP BY cid
This is more reliable, as it generates the Grade in the sub-query, and then appends it to the main table.
SELECT cid, (
SELECT grade
FROM grades g2
WHERE g2.cid = g1.cid
ORDER BY g_point
LIMIT 1
) AS grade
FROM grades g1
GROUP BY cid
You can use the following query:
SELECT DISTINCT m1.cid, m1.grade
FROM mytable AS m1
INNER JOIN (
SELECT cid, MIN(g_point) AS maxGrade
FROM mytable
GROUP BY cid ) m2
ON m1.cid = m2.cid AND m1.g_point = m2.maxGrade
The derived table contains the minimum g_point per cid. If you join it back to the original table, then you can get the maximum grade per cid.
Demo here
EDIT:
You can alternatively use a correlated sub-query:
SELECT cid, (SELECT grade
FROM mytable AS m2
WHERE m2.cid = m1.cid
ORDER BY g_point LIMIT 1) AS maxGrade
FROM mytable AS m1
GROUP BY cid
Demo here
EDIT2:
It looks like you want to get the grade having the maximum number of occurrences per cid. In case there are more than one grades sharing this maximum number, then fetch the grade with the lowest g_point.
You can do it using variables:
SELECT cid, grade
FROM (
SELECT cid, grade,
#row_number := IF (#cid <> cid,
IF (#cid := cid, 1, 1),
IF (#cid := cid, #row_number+1, #row_number+1)) AS rn
FROM (
SELECT cid, grade,
COUNT(*) AS cnt,
(SELECT g_point
FROM mytable AS m2
WHERE m1.grade = m2.grade
LIMIT 1) AS g_point
FROM mytable AS m1
GROUP BY cid, grade
) t
CROSS JOIN (SELECT #row_number:=-1, #cid:=-1) AS vars
ORDER BY cid, cnt DESC, g_point
) s
WHERE rn = 1
Demo here
Something to think about...
SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+
SELECT i
, CONCAT(CHAR((i/2)+64),IF(MOD(i,2)=1,'+',''))n
FROM ints
WHERE i > 0;
+---+------+
| i | n |
+---+------+
| 1 | A+ |
| 2 | A |
| 3 | B+ |
| 4 | B |
| 5 | C+ |
| 6 | C |
| 7 | D+ |
| 8 | D |
| 9 | E+ |
+---+------+
Im having a problem from mySQL , actually i want to show the fullname of the student with the highest votes in the subject.
here's the code
$query="SELECT student_tbl.fullname, student_tbl.subject,
COUNT(student_tbl.fullname)AS rating
FROM student_tbl
INNER JOIN subject_tbl
ON student_tbl.subject= subject_tbl.subjname
GROUP BY subject ORDER BY num,
COUNT(fullname) DESC";
student_tbl subject_tbl
| fullname | subject| | subjname | num |
==================== ================
| John | Math | | Math | 1 |
| Rey | Math | | Science | 2 |
| Wey | Science | | English | 3 |
| Xin | Science | =================
| Nick | English |
| Mi | English |
| John | Math |
| Xin | Science |
| Mi | English |
======================
Here's the output to my codes:
| fullname | Subject | Votes |
============================
| John | Math | 2 |
| Wey | Science | 2 |
| Nick | English | 2 |
And This is the output i want:
| fullname | Subject | Votes |
============================
| John | Math | 2 |
| Xin | Science | 2 |
| Mi | English | 2 |
SELECT s1.fullname, s1.subject, COUNT(s1.fullname) AS rating
FROM student_tbl s1
INNER JOIN subject_tbl s2
ON s1.subject= s2.subjname
GROUP BY subject, fullname
HAVING COUNT(fullname) = (
SELECT COUNT(fullname) FROM student_tbl
WHERE s1.subject = subject
GROUP BY fullname
ORDER BY COUNT(fullname) DESC
LIMIT 1
)
ORDER BY num, COUNT(fullname) DESC
SqlFiddle : http://sqlfiddle.com/#!2/aea20
I highly suggest you to use numeric keys and not string keys.
Not pretty but it works. I grouped the votes first and then got the rank.
SQL FIDDLE DEMO
SELECT fullname, subject, votes
FROM (SELECT fullname,subject,votes,
(CASE subject WHEN #curtype THEN #currow := #currow + 1
ELSE #currow := 1 AND #curtype := subject end ) + 1 AS rank
FROM (SELECT fullname,subject,Count(1) AS Votes
FROM student_tbl
GROUP BY fullname,subject) a,(SELECT #currow := 0, #curtype := '') r
ORDER BY subject,votes DESC) b
WHERE rank = 1
I'm a bit stuck with a php/Mysql Query. I got 2 tables :
table_users table_ranks
---------------- ------------------------
| id | points | | name | points_needed |
---------------- ------------------------
| 1 | 2 | | lvl0 | 0 |
| 2 | 10 | | lvl1 | 10 |
| 3 | 21 | | lvl2 | 20 |
| 4 | 29 | | lvl3 | 30 |
---------------- ------------------------
I need an ouput like this :
User_1 = lvl0 (because user has 2 points)
User_2 = lvl1 (because user has just reached 10 points)
...
User_4 = lvl2 (because user has not yet reached 30 points)
Think you :)
Regards.
You can do it like this
SELECT
tu.id,
tr.name,
tu.points
FROM table_ranks as tr
LEFT JOIN (SELECT * FROM table_ranks LIMIT 1,69596585953484) as l
ON l.points_needed = (SELECT MIN(points_needed) FROM table_ranks WHERE points_needed > tr.points_needed limit 1)
LEFT OUTER JOIN table_users AS tu ON tu.points >= tr.points_needed AND tu.points < l.points_needed
WHERE tu.id IS NOT NULL
group by tu.id
Fiddle
Output
-------------------------
| id | points | name |
-------------------------
| 1 | lvl0 | 2 |
| 2 | lvl1 | 10 |
| 3 | lvl2 | 21 |
| 4 | lvl2 | 29 |
-------------------------
give this a try, a little bit messy due to table design,
SELECT u.*, r.name
FROM table_users u
INNER JOIN
(
SELECT x.name,
x.points_needed start_point,
COALESCE(y.points_needed - 1, 2000000) end_point
FROM
(
SELECT name, points_needed, #rank:=#rank+1 ranks
FROM table_ranks a, (SELECT #rank:=0) b
ORDER BY points_needed
) x
LEFT JOIN
(
SELECT name, points_needed, #rank1:=#rank1+1 ranks
FROM table_ranks a, (SELECT #rank1:=0) b
ORDER BY points_needed
) y ON x.ranks+1 = y.ranks
) r ON u.points BETWEEN r.start_point AND r.end_point
SQLFiddle Demo
I have table :
==========================================================
|id | before | after | freq | id_sentence | document_id |
==========================================================
| 1 | a | b | 1 | 0 | 1 |
| 2 | c | d | 1 | 1 | 1 |
| 3 | e | f | 1 | 1 | 1 |
| 4 | g | h | 2 | 0 | 2 |
==========================================================
I want to get the number of data depend on the id_sentence and freq so the result must be 1 2 1
here's the code :
$query = mysql_query("SELECT freq FROM tb where document_id='$doc_id' ");
while ($row = mysql_fetch_array($query)) {
$stem_freq = $row['freq'];
$total = $total+$stem_freq;
but the result is still wrong. please, help me.. thank you :)
If I understand your question, you are trying the calculate the sum of freq for each distinct id_sentence for a particular document_id.
Try the following SQL:
SELECT id_sentence, SUM(freq) as freq FROM tb WHERE document_id = 1 GROUP BY(id_sentence)
The result will be rows of data with the id_sentence and corresponding total freq. No need to manually sum things up afterwards.
See this SQL Fiddle: http://sqlfiddle.com/#!2/691ed/8
I think you could do something like
SELECT count(*) AS count FROM tb GROUP BY(id_sentence,freq)
to do the counting you want. You could even do something like
SELECT count(*) AS count, id_sentence, freq FROM tb GROUP BY(id_sentence,freq)
to know which id_sentence,freq combination the count is for.