I have two tables, the first is players
---------------------------------------------
| player_id | player_score | player_game_id |
---------------------------------------------
| 1 | 274 | 1 |
---------------------------------------------
| 2 | 281 | 1 |
---------------------------------------------
| 3 | 156 | 2 |
---------------------------------------------
| 4 | 199 | 2 |
---------------------------------------------
| 5 | 120 | 2 |
---------------------------------------------
And another table for games
-----------------------
| game_id | game_name |
-----------------------
| 1 | gameone |
-----------------------
| 2 | gametwo |
-----------------------
I would like to have this result
----------------------------------------------------
| player_id | player_score | player_rank | game_id |
----------------------------------------------------
| 2 | 281 | 1 | 1 |
----------------------------------------------------
| 1 | 274 | 2 | 1 |
----------------------------------------------------
| 4 | 199 | 1 | 2 |
----------------------------------------------------
| 3 | 156 | 2 | 2 |
----------------------------------------------------
| 5 | 120 | 3 | 2 |
----------------------------------------------------
Have anyone idea how to achieve this in mysql?
Thank you very much
You want rank() or row_number():
select p.*,
rank() over (partition by player_game_id order by player_score desc) as rank
from players
order by player_game_id, player_score desc;
If two players have the same score, then rank() gives them the same ranking. row_number() will arbitrarily assign them adjacent rankings.
The above works on MySQL 8+. In earlier versions you have two options -- subqueries and variables. Here is an example using a correlated subquery:
select p.*,
(select 1 + count(*)
from players p2
where p2.player_game_id = p.player_game_id and
p2.player_score > p.player_score
) as ranking
from players
order by player_game_id, player_score desc;
This is not as efficient as rank(). But with an index on players(player_game_id, player_score) and not too many players per game, then this should have reasonable performance.
Related
I have the following result set...
Name | Team | Score
A | 1 | 10
B | 1 | 11
C | 2 | 9
D | 2 | 15
and I want to add an extra column to the results set for the team score so I can sort on it and end up with the following data set...
Name | Team | Score | TeamScore
D | 2 | 15 | 24
C | 2 | 9 | 24
B | 1 | 11 | 21
A | 1 | 10 | 21
So I end up with the top team first with the members in order.
My actual data is way more complicated than this and pulls in data from several tables but if you can solve this one I can solve my bigger issue!
Join the table to a query that returns the total for each team:
select t.*, s.teamscore
from tablename t
inner join (
select team, sum(score) teamscore
from tablename
group by team
) s on s.team = t.team
order by s.teamscore desc, t.team, t.score desc
See the demo.
Results:
| Name | Team | Score | teamscore |
| ---- | ---- | ----- | --------- |
| D | 2 | 15 | 24 |
| C | 2 | 9 | 24 |
| B | 1 | 11 | 21 |
| A | 1 | 10 | 21 |
In MySQL 8+, we can simplify and just use SUM as an analytic function:
SELECT
Name,
Team,
Score,
SUM(Score) OVER (PARTITION BY Team) AS TeamScore
FROM yourTable
ORDER BY
TeamScore DESC,
Score;
How do I solve this one? None of my queries works and I've tried few.
I've got to return details of two doctors who ordered the most analysis including the number of analysis they have ordered. That last part of the sentence is what really drives me mad.
To work with I've got these two tables:
mysql> select * from DOCTORES;
+-----------+---------------------------+--------------+-----------+
| DNI_DOC | NOMBRE_DOC | ESPECIALIDAD | TELEFONO |
+-----------+---------------------------+--------------+-----------+
| 22888444O | MATEO DÍAZ, RAMÓN | 3 | 659876457 |
| 22909456Y | HERAS PRADO, ANTONIA | 1 | 676234598 |
| 23456398F | GÓMEZ DAVID, ADRIÁN | 1 | 646768454 |
| 25349857H | BURGOS CASA, CANDY | 2 | 659758476 |
| 55776898K | RAMÓN CORONADO,LUIS | 3 | 654364736 |
| 78988484B | CONRADO ALONSO, JOSE | 2 | 645878745 |
| 88647389P | DOMÍNGUEZ GÓMEZ, MANUEL | 1 | 623787343 |
+-----------+---------------------------+--------------+-----------+
and:
mysql> select * from PETICIONES;
+--------+------------+--------+-----------+-----------+
| ID_PET | FECHA_PET | ID_ANA | DNI_PAC | DNI_DOC |
+--------+------------+--------+-----------+-----------+
| 1 | 2008-01-03 | 2 | 71515623A | 23456398F |
| 2 | 2008-05-10 | 2 | 33788976F | 55776898K |
| 3 | 2008-05-08 | 3 | 79876867X | 23456398F |
| 4 | 2008-05-11 | 4 | 44787345H | 55776898K |
| 5 | 2008-05-12 | 2 | 19887234W | 25349857H |
| 6 | 2008-05-05 | 4 | 22897576R | 55776898K |
| 7 | 2008-03-15 | 5 | 44787345H | 88647389P |
| 8 | 2008-03-19 | 1 | 71515623A | 23456398F |
| 9 | 2008-03-26 | 2 | 71515623A | 78988484B |
| 10 | 2008-03-15 | 2 | 19887234W | 88647389P |
| 11 | 2008-03-15 | 3 | 33788976F | 55776898K |
| 12 | 2008-03-26 | 2 | 44787345H | 23456398F |
+--------+------------+--------+-----------+-----------+
I tried this:
select
NOMBRE_DOC
from
DOCTORES
where
DNI_DOC IN (select DNI_DOC
from PETICIONES
group by ID_ANA
order by count(*) desc
limit 2)
group by
DNI_DOC;
and that:
SELECT
DNI_DOC, ID_ANA, COUNT(ID_ANA) AS count
FROM
TIPOS_ANALISIS
WHERE
ID_ANA = (SELECT ID_ANA
FROM
(SELECT
ID_ANA, COUNT(ID_ANA) as AnaCount
FROM
PETICIONES
GROUP BY
by ID_ANA
ORDER BY
AnaCount DESC
LIMIT 1) t1)
GROUP
BY ID_ANA;
and that:
select a.* from DOCTORES a
-> where a.DNI_DOC = ( SELECT b.DNI_DOC from PETICIONES b
-> group by d.ID_ANA
-> order by count(ID_ANA) DESC
-> limit 2 );
you can't even imagine how frustrating it is when you say it's a simple query... Why it isn't simple to me is a mystery (provided that I am really not a dummy).
Expected output would be something like this:
+-----------+---------------------------+--------------+-----------+
| DNI_DOC | NOMBRE_DOC | ID_ANA | count |
+-----------+---------------------------+--------------+-----------+
| 22888444O | MATEO DÍAZ, RAMÓN | 3 | 6 |
+-----------+---------------------------+--------------+-----------+
I believe you are severely overcomplicating this. Join the 2 tables on DNI_DOC field, group by the doctor's id and name (and any other details you may want to include in the select list), and count the number of distinct ID_ANAs.
SELECT d.DNI_DOC, d.NOMBRE_DOC, COUNT(distinct ID_ANA) AS count
FROM DOCTORES d
INNER JOIN PETICIONES t ON d.DNI_DOC=t.DNI_DOC
GROUP BY d.DNI_DOC, d.NOMBRE_DOC
ORDER BY COUNT(distinct ID_ANA) DESC
LIMIT 2
If you need the total number of peticiones per doctor, then remove the distinct from the count.
Here is what I would do :
select d.*, count(p.ID_PET) as TOTAL_PETICIONES from DOCTORES d
inner join PETICIONES p on p.DNI_DOC = d.DNI_DOC
group by d.DNI_DOC
order by count(ID_ANA) DESC
limit 2
This is not tested and write here so please correct me for typos ;)
Using a join will provide a nice output. Grouping by DOCTORES to be able to count the PETICIONES per DOCtORES
EDIT : Something like that. The output won't be good because I have issues to understand the column content.
i am loosing it over the following problem:
i have a table with participants and points. each participant can have up to 11 point entries of which i only want the sum of the top 6.
in this example lets say we want the top 2 of 3
+----+---------------+--------+
| id | participantid | points |
+----+---------------+--------+
| 1 | 1 | 11 |
+----+---------------+--------+
| 2 | 3 | 1 |
+----+---------------+--------+
| 3 | 3 | 4 |
+----+---------------+--------+
| 4 | 2 | 3 |
+----+---------------+--------+
| 5 | 1 | 5 |
+----+---------------+--------+
| 6 | 2 | 10 |
+----+---------------+--------+
| 7 | 2 | 9 |
+----+---------------+--------+
| 8 | 1 | 3 |
+----+---------------+--------+
| 9 | 3 | 4 |
+----+---------------+--------+
as a result i want something like
+---------------+--------+
| participantid | points |
+---------------+--------+
| 2 | 19 |
+---------------+--------+
| 1 | 16 |
+---------------+--------+
| 3 | 8 |
+---------------+--------+
(it should be ordered DESC by the resulting points)
is this at all possible with mysql? in one query?
oh and the resulting participant ids should be resolved into the real names from another 'partcipant' table where
+----+------+
| id | name |
+----+------+
| 1 | what |
+----+------+
| 2 | ev |
+----+------+
| 3 | er |
+----+------+
but that should be doable with a join at some point... i know...
Using one of the answers from ROW_NUMBER() in MySQL for row counts, and then modifying to get the top.
SELECT ParticipantId, SUM(Points)
FROM
(
SELECT a.participantid, a.points, a.id, count(*) as row_number
FROM scores a
JOIN scores b ON a.participantid = b.participantid AND cast(concat(a.points,'.', a.id) as decimal) <= cast(concat(b.points,'.', b.id) as decimal)
GROUP BY a.participantid, a.points, a.id
) C
WHERE row_number IN (1,2)
GROUP BY ParticipantId
Had an issue with ties until I arbitrarily broke them with the id
I have three table
td_idea
|------------|-------------|
| idea_id | idea_name |
|------------|-------------|
then td_idea_comment
|-----------|------------|----------
|comm_id | idea_id | user_id |
|-----------|------------|----------|
and td_idea_like
|-----------|------------|----------
|comm_id | idea_id | user_id |
|-----------|------------|----------|
Now I need to use a query which will order the idea in ascending order based on the no. of votes in td_idea_like and no. of comments on td_idea_comment.
A example to the three tables is as follows
td_idea
|------------|-------------|
| idea_id | idea_name |
|------------|-------------|
| 1 | Pink Ruby |
|------------|-------------|
| 2 | Black_ruby |
|------------|-------------|
td_idea_comment
|------------|-------------|---------------|
| comm_id | idea_id | user_id |
|------------|-------------|---------------|
| 1 | 1 | 1 |
|------------|-------------|---------------|
| 2 | 2 | 1 |
|------------|-------------|---------------|
| 3 | 1 | 2 |
|------------|-------------|---------------|
| 4 | 1 | 3 |
|------------|-------------|---------------|
td_idea_like
|------------|-------------|---------------|
| like_id | idea_id | user_id |
|------------|-------------|---------------|
| 1 | 1 | 1 |
|------------|-------------|---------------|
| 2 | 2 | 1 |
|------------|-------------|---------------|
| 3 | 1 | 2 |
|------------|-------------|---------------|
| 4 | 1 | 3 |
|------------|-------------|---------------|
I used this query
SELECT * FROM td_idea,td_idea_comment,tyd_idea_like
WHERE td_idea.idea_id=td_idea_comment.idea_id
AND td_idea.idea_id=td_idea_like.idea_id
Order BY (SELECT COUNT(*) AS tot_comment FROM td_idea,td_idea_comment
WHERE td_idea.idea_id=td_idea_comment.idea_id),
(SELECT COUNT(*) AS tot_like FROM td_idea,td_idea_like
WHERE td_idea.idea_id=td_idea_like.idea_id)
but it returns me zero if in any case either there is no row in td_idea_comment based on a particular idea or no row in td_idea_like based on a particular idea.
Say:
idea id 1 has 3 likes 3 comments
idea id 2 has 1 likes 2 comments
idea id 3 has 0 likes 4 comments
then for idea id 3, the resultant is returned as 0.
While I want it to be sorted as this
idea id 1(since 3+3)
idea id 3(since 0+4)
idea id 2(since 1+2)
SELECT a.idea_id,
a.idea_name,
COUNT(DISTINCT b.like_ID) totalLikes,
COUNT(DISTINCT c.comm_ID) totalComment
FROM td_idea a
LEFT JOIN td_idea_like b
ON a.idea_ID = b.idea_ID
LEFT JOIN td_idea_comment c
ON a.idea_ID = c.idea_ID
GROUP BY a.idea_id, a.idea_name
ORDER BY COUNT(DISTINCT b.like_ID) + COUNT(DISTINCT c.comm_ID) DESC
SQLFiddle Demo
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
I have a problem, please see my database:
-------------------
| id | article_id |
-------------------
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 3 |
| 8 | 3 |
| 9 | 3 |
| 10 | 3 |
And I want to receive something like this (order by votes, from max to min):
---------------------------
| id | article_id | votes |
---------------------------
| 1 | 3 | 5 |
| 2 | 1 | 3 |
| 3 | 2 | 2 |
Could you please help me to write proper sql query?
SET #currentRow = 0;
SELECT #currentRow := #currentRow + 1 AS id, t.article_id, t.c AS `votes`
FROM (
SELECT article_id, count(*) as `c`
FROM table_votes
GROUP BY article_id
) t
ORDER BY t.c DESC
please note that you can't select an id column like this in this context, and your "expected result" is incorrect. I tried to adapt it at a maximum.
cheers
SELECT article_id, COUNT(article_id) AS votes
FROM votes_table
GROUP BY article_id
ORDER BY votes DESC;