I am trying to create a query that allows me to select the data like shown below
id Counter_Type Champion_Name Counter_Lane
---|------------|------------|--------------
1 | 1 | Ahri | 1
2 | 1 | Ahri | 2
5 | 1 | Ahri | 2
3 | 1 | Ahri | 3
4 | 1 | Ahri | 2
6 | 1 | Teemo | 1
7 | 1 | Warwick | 4
8 | 1 | Warwick | 4
It should count the Counter_Lane and then the Counter_Type with the most should be shown for that name as shown below how it should show the data:
id Counter_Type Champion_Name Counter_Lane
---|------------|------------|--------------
1 | 1 | Ahri | 2
2 | 1 | Teemo | 1
3 | 1 | Warwick | 4
I have tried the following code and its the closest I have came for over 3 hours now, so could someone help please.
SELECT
a.Counter_Type, Champion_For, a.Counter_Lane, a.Champion_Name, COUNT(*) as Amount, sum(vote_type = 'up') as Upvotes, sum(vote_type = 'down') as Downvotes, sum(vote_type = 'up')-sum(vote_type = 'down') as Totalvotes
FROM Champion_Counters_Data a
JOIN ( SELECT c.Counter_Lane, c.Champion_Name, COUNT(*) magnitude
FROM Champion_Counters_Data c
WHERE
Champion_For = "Aatrox" AND Counter_Type = 1 GROUP BY Champion_Name, Counter_Lane ORDER BY magnitude) b ON a.Champion_Name = b.Champion_Name AND b.Counter_Lane = a.Counter_Lane
GROUP BY Champion_Name
SELECT * FROM your_table GROUP BY MAX(Counter_Lane)
This query is based on the output you want from the table you have given.
You will need many subqueries as MySQL doesn't allow windows function or CTE.
Rextester Demo
SELECT #rn := #rn + 1 as id,
t3.*
from
(select t1.*
FROM
(SELECT counter_type,
champion_name,
counter_lane,
count(*) AS cnt
FROM table53
GROUP BY champion_name,
counter_lane
) t1
INNER JOIN
(SELECT counter_type,
champion_name,
max(cnt) AS mcnt
FROM
(SELECT counter_type,
champion_name,
counter_lane,
count(*) AS cnt
FROM table53
GROUP BY champion_name,
counter_lane
) t
GROUP BY counter_type,
champion_name
) t2
ON t1.counter_type=t2.counter_type
AND t1.champion_name=t2.champion_name
AND t1.cnt=t2.mcnt
) t3
,(SELECT #rn := 0) t
;
Output
+-----+--------------+---------------+--------------+-----+
| id | counter_type | champion_name | counter_lane | cnt |
+-----+--------------+---------------+--------------+-----+
| 1 | 1 | Ahri | 2 | 3 |
| 2 | 1 | Teemo | 1 | 1 |
| 3 | 1 | Warwick | 4 | 2 |
+-----+--------------+---------------+--------------+-----+
Idea is to first group by champion_name and counter_lane and get the count . So for Ahri you will get cnt as 3. Now use another subquery to get corresponding counter_lane, which will be 2 for Ahri. At last, use a sequence number to generate id as 1,2,3 etc.
Try following SQL statement:
SELECT Counter_Type , Champion_Name, MAX(Counter_Lane) 'Counter_Lane'
FROM(
SELECT Counter_Type , Champion_Name , Counter_Lane
FROM Champion_Counters_Data
GROUP BY Counter_Type , Champion_Name
HAVING COUNT(Counter_Lane) >= 2
) tb
GROUP BY Counter_Type , Champion_Name
Related
I have a table like so (I'm not sure how to format tables)
Category / Products / Purchases
1 | A | 12
1 | B | 13
1 | C | 11
2 | A | 1
2 | B | 2
2 | C | 3
Expected output:
1 | B | 13
2 | C | 3
However I keep on getting
1 | A | 13
2 | A | 3
ie. It just selects the first occurrence of the second column.
Here is my code:
SELECT Category, Products, MAX(Purchases) FROM myTable GROUP BY Category;
Use filtering in the where clause:
select t.*
from t
where t.purchases = (select max(t2.purchases) from t t2 where t2.category = t.category);
With NOT EXISTS:
select m.* from myTable m
where not exists (
select 1 from myTable
where category = m.category and purchases > m.purchases
)
See the demo.
Results:
| Category | Products | Purchases |
| -------- | -------- | --------- |
| 1 | B | 13 |
| 2 | C | 3 |
You can use row_number() to identify max purchase for each group or replace rownumber() to rank() if there are ties of max purchases for each group
Select Category, Products,
Purchases from (Select Category,
Products,
Purchases,
row_number() over (partition by
category, products order by
purchases desc) rn from table) t
where t.rn=1
)
What I have
So I'm running this statement:
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN
vote_item v
ON i.id = v.item_to_map_id
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
ORDER BY
item_id asc, score desc;
And I'm getting the following table:
+----+---------+----------------+---------------------+-------+
| id | item_id | item_to_map_id | date | score |
+----+---------+----------------+---------------------+-------+
| 1 | 1 | 1 | 2017-07-05 09:38:23 | 3 |
| 3 | 1 | 3 | 2017-07-05 09:38:23 | 0 |
| 2 | 1 | 2 | 2017-07-05 09:38:23 | -1 |
| 4 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 5 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 6 | 2 | NULL | 2017-07-05 09:38:24 | 0 |
+----+---------+----------------+---------------------+-------+
What I'm trying to do is select the first X of the repeated item_ids based on some ordering, for example, score or date.
What I've tried
I looked at this answer https://stackoverflow.com/a/1902167/6554121 and tried a modified version:
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN
vote_item v
ON i.id = v.item_to_map_id
WHERE
(
SELECT
COUNT(*)
FROM
item_to_map i2
WHERE
i2.item_id = i.item_id
) < 3
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
ORDER BY item_id asc, score desc;
However this returns me no results
What I expected
If ordered by score:
+----+---------+----------------+---------------------+-------+
| id | item_id | item_to_map_id | date | score |
+----+---------+----------------+---------------------+-------+
| 1 | 1 | 1 | 2017-07-05 09:38:23 | 3 |
| 3 | 1 | 3 | 2017-07-05 09:38:23 | 0 |
| 4 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
| 5 | 2 | NULL | 2017-07-05 09:38:23 | 0 |
+----+---------+----------------+---------------------+-------+
You can achieve this using session variables which simulate row number functionality:
SET #row_number = 0;
SET #item_id = 1;
SELECT t.id, t.item_id, t.item_to_map_id, t.date, t.score
FROM
(
SELECT
#row_number:=CASE WHEN #item_id = t.item_id
THEN #row_number + 1 ELSE 1 END AS rn,
#item_id:=t.item_id AS item_id,
t.id, t.item_to_map_id, t.date, t.score
FROM
(
SELECT
i.id,
i.item_id,
v.item_to_map_id,
i.date,
COALESCE( SUM(CAST(CAST(v.score AS char) AS SIGNED)), 0 ) AS score
FROM item_to_map i
LEFT JOIN vote_item v
ON i.id = v.item_to_map_id
GROUP BY
i.id, i.item_id, i.date, v.item_to_map_id
) t
ORDER BY
t.item_id, t.score DESC
) t
WHERE t.rn <= 2 -- this restricts to the first two rows per item_id group
-- as ordered by the logic in your ORDER BY clause
As far as I know, there is no nice way to get the first X records of a group in MySQL, unless your schema coincidentally happens to have row numbers already for each group. Using session variables as above is one way to handle this, and the performance might even be good as well.
Demo here:
Rextester
I have the following table:
+----+-----------+-----------+
| id | teacherId | studentId |
+----+-----------+-----------+
| 1 | 1 | 4 |
| 2 | 1 | 2 |
| 3 | 1 | 1 |
| 4 | 1 | 3 |
| 5 | 2 | 2 |
| 6 | 2 | 1 |
| 7 | 2 | 3 |
| 8 | 3 | 9 |
| 9 | 3 | 6 |
| 10 | 1 | 6 |
+----+-----------+-----------+
I need a query to find two teacherId's with maximum number of common studentId's.
In this case teachers with teacherIds 1,2 have common students with studentIds 2, 1, 3, which is greater than 1,3 having common students 6.
Thanks in Advance!
[Edit]: After several hours I've had the following solution:
SELECT * FROM (
SELECT r1tid, r2tid, COUNT(r2tid) AS cnt
FROM (
SELECT r1.teacherId AS r1tid, r2.teacherId AS r2tid
FROM table r1
INNER JOIN table r2 ON r1.studentId=r2.studentId AND r1.teacherId!=r2.teacherId
ORDER BY r1tid
) t
GROUP BY r1tid, r2tid
ORDER BY cnt DESC
) t GROUP BY cnt ORDER BY cnt DESC LIMIT 1;
I was sure that there must exist more short and elegant solution, but I could not find it.
You would do this with a self-join. Assuming no duplicates in the table:
select t.teacherid, t2.teacherid, count(*) as NumStudentsInCommon
from table t join
table t2
on t.studentid = t2.studentid and
t.teacherid < t2.teacherid
group by t.teacherid, t2.teacherid
order by NumStudentsInCommon desc
limit 1;
If you had duplicates, you would just replace count(*) with count(distinct studentid), but count(distinct) requires a bit more work.
select t.teacherId, t2.teacherId, sum(t.studentId) as NumStudentsInCommon
from table1 t join
table1 t2
on t.studentId = t2.studentId and
t.teacherId < t2.teacherId
group by t.teacherId, t2.teacherId
order by NumStudentsInCommon desc
I'm trying to setup a high score board to be displayed in my arcade game room. My target is to display the top 5 players for each game from the table GAME.
I've created three tables:
Table GAME :
+----------+--------------+
| id_game | name_game |
+----------+--------------+
| 1 | PAC MAN |
| 2 | GALAXIAN |
| 3 | XEVIOUS |
table PLAYER :
+----------+---------------+
| id_player | name_player |
+----------+---------------+
| 1 | BRUNO |
| 2 | STEVE |
table SCORE :
+----------+----------+-----------+------+------+
| id_score | id_game | id_player | date | score |
+----------+----------+-----------+------+------+
| 1 | 1 | 1 | 01/10/15 | 230234 |
| 2 | 1 | 2 | 04/10/15 | 120234 |
| 3 | 1 | 1 | 03/10/15 | 440224 |
| 4 | 1 | 1 | 06/10/15 | 200000 |
| 5 | 1 | 2 | 09/10/15 | 330233 |
| 6 | 1 | 1 | 01/10/15 | 510000 |
| 7 | 2 | 1 | 01/10/15 | 730874 |
| 8 | 2 | 2 | 01/10/15 | 990900 |
| 9 | 3 | 1 | 01/10/15 | 444000 |
I would like some help to build the sql code to produce something like this :
PAC MAN
1. BRUNO 510000 PTS 01/10/15
2. STEVE 330233 PTS 09/10/15
3. XXXXX 230233 PTS 02/10/14
4. YYYYY 130233 PTS 06/10/15
5. ZZZZZ 030233 PTS 10/10/13
GALAXIAN
1. STEVE 990900 PTS 01/10/15
2. BRUNO 730874 PTS 01/10/15
3. XXXXX 230233 PTS 02/10/14
4. YYYYY 130233 PTS 06/10/15
5. ZZZZZ 030233 PTS 10/10/13
If the same player did more than one score on the same game, only his/her best score should be displayed. Can you help me to set up the code for doing this?
SQL fiddle
SELECT MAX(s.score) AS score, p.name_player, g.name_game
FROM GAME g
JOIN SCORE s ON s.id_game = g.id_game
JOIN PLAYER p ON p.id_player = s.id_player
GROUP BY p.id_player, g.id_game
ORDER BY g.id_game, score
Well, I still have an issue with your query above :-(
The query displays well the best score of per unique player, but the date associated is not correct. The 'date' field still gives the first date from the first score done per player.
Let me illustrate this. I just add the DATE value to the first line of your query, which gives :
SELECT MAX(s.score) AS score, p.name_player, g.name_game, date
FROM GAME g
JOIN SCORE s ON s.id_game = g.id_game
JOIN PLAYER p ON p.id_player = s.id_player
GROUP BY p.id_player, g.id_game
ORDER BY g.id_game, score
+----------+----------+-----------+------+------+
| id_score | id_game | id_player | date | score |
+----------+----------+-----------+------+------+
| 1 | 1 | 1 | 01/10/12 | 230234 |
| 2 | 1 | 1 | 04/10/13 | 120234 |
| 3 | 1 | 1 | 03/10/14 | 440224 |
Your query will return this :
440224 1 1 01/10/12
But I'm expecting this : 440224 1 1 03/10/14
I tried to add max(date) here in there but I guess there is obviously something more complex to do?
You would want something like this. The first query is probably the one you would actually use to run it against your own tables. The second example you can run directly in mysql and fudge the data as required.
select
g.name_game,
p.name_player,
max(s.score),
s.date
from
game g
inner join score s on
s.id_game = g.id_game
inner join player p on
p.id_player = s.id_player
where
g.name_game = 'PAC MAN'
group by
g.name_game,
p.name_player
ORDER BY
s.score asc
LIMIT
5;
select
g.name_game,
p.name_player,
max(s.score),
s.date
from
(
select 1 id_game, 'PAC MAN' name_game union all
select 2 id_game, 'GALAXIAN' name_game union all
select 3 id_game, 'XEVIOUS' name_game
) g
inner join (
select 1 id_score, 1 id_game, 1 id_player, '01/10/15' date, 230234 score union all
select 2 id_score, 1 id_game, 2 id_player, '04/10/15' date, 120234 score union all
select 3 id_score, 1 id_game, 1 id_player, '03/10/15' date, 440224 score union all
select 4 id_score, 1 id_game, 1 id_player, '06/10/15' date, 200000 score union all
select 5 id_score, 1 id_game, 2 id_player, '09/10/15' date, 330233 score union all
select 6 id_score, 1 id_game, 1 id_player, '01/10/16' date, 410000 score union all
select 6 id_score, 1 id_game, 1 id_player, '01/10/15' date, 510000 score union all
select 7 id_score, 2 id_game, 1 id_player, '01/10/15' date, 730874 score union all
select 8 id_score, 2 id_game, 2 id_player, '01/10/15' date, 990900 score union all
select 9 id_score, 3 id_game, 1 id_player, '01/10/15' date, 444000 score
) s on
s.id_game = g.id_game
inner join (
select '1' id_player, 'BRUNO' name_player union all
select '2' id_player, 'STEVE' name_player
) p on
p.id_player = s.id_player
where
g.name_game = 'PAC MAN'
group by
g.name_game,
p.name_player
ORDER BY
s.score asc
LIMIT
5;
Maybe next time post what you have tried?
You could also use a group by if you wanted them all in the same query. Just replace [game_name] with the name of the game you want.
Given the following table:
id | group_s | name
_____________________
1 | 1 | pollo
2 | 1 | cordero
3 | 1 | cerdo
4 | 2 | tomates
5 | 2 | naranjas
6 | 2 | manzanas
I would like to randomly select one line from every group.
Example of possible outputs (since it is random):
id | group_s | name
_____________________
3 | 1 | cerdo
5 | 2 | naranjas
or
id | group_s | name
_____________________
1 | 1 | pollo
6 | 2 | manzanas
and so on..
I don't have a clue how to do it. I suppose I should multiselect the table.
I did try the following without success:
SELECT T2.* FROM (
SELECT group_s
FROM mytable
GROUP BY group_s ORDER BY RAND() LIMIT 1) AS T1
JOIN mytable AS T2
ON T1.group_s = T2.group_s;
Use the window function ROW_NUMBER() OVER(PARTITION BY group_s) with ORDER BY NEWID() to randomly get the ordering, something like this:
WITH CTE
AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY group_s
ORDER BY newid()) AS RN
FROM yourTable
)
SELECT id , group_s , name
FROM CTE
WHERE RN = 1;
See it in action here:
SQL Fiddle Demo