简体   繁体   中英

Sql get all n:th rows depending on related table value

Hello I'm doing a sport statistics site, which provides alot of challenges when it comes to the sql, but before this point I have been able to solve all the queries getting the collected stats I want. However now I find myself asking for some help.

I'm using a mysql database.

It has a games table, with all games and it has a gameevents table with all gameevents, like goals and penalties.

Now I want to collect all the game winning goals. Which means i want to get all games where our score is bigger than opposing team score, and the get the goal that means that our team comes out one goal ahead. So if ourscore is 6 and theirscore (opposing team) is 2 i want to collect the third goal that our team made (gameevent = 1, thisteam = 1) from gameevents table

table games:
id
ourscore
theirscore

table gameevents:
id
game_id
player_id
eventtype
thisteam
time

Below query would get all goal rows that our team made in games which we won

select ge.* from gameevents ge
inner join games g
on ge.game_id = g.id
where g.ourscore > g.theirscore
and ge.eventtype = 1
and ge.thisteam = 1

Below query shows a bit of what I want to do now, however the Limit clause will not take any parameters.

select ge.* from gameevents ge
where ge.id = (
    select ge2.id 
    from gameevents ge2
    inner join games g
    on ge2.game_id = g.id
    where g.ourscore > g.theirscore
    and ge2.eventtype = 1
    and ge2.thisteam = 1
    order by ge2.time
    limit g.theirscore + 1, 1
)

So if our team has won three games with 2-1, 4-1 and 6-3 i want to get the row for the second goal in game one, the second goal on game two and the fourth goal in game three.

Any ideas to have me moving forward?

I wish to solve it without declaring variables and stuff, just a plain old school query.

edit:

Feels like I'm so close. Have tried to use some variables to make it possible since i saw a possible solution in row_number() but that was only in mssql.

This link pointed me in this direction: http://www.explodybits.com/2011/11/mysql-row-number/

This is where I am now:

SELECT subquery.id, game_id, player_id, eventtype, time
FROM
(
    SELECT  @row_num := IF(@prev_value=ge.game_id,@row_num+1,1) AS RowNumber
    ,ge.id
    ,ge.game_id
    ,ge.player_id
    ,ge.eventtype
    ,ge.time
    ,RowNumber
    ,@prev_value := ge.game_id
    FROM gameevents AS ge
    INNER JOIN games AS g
    ON ge.game_id = g.id,
        (SELECT @row_num := 1) x,
        (SELECT @prev_value := '') y
    WHERE g.ourscore > g.theirscore
    AND ge.eventtype = 1
    AND ge.thisteam = 1
    ORDER BY ge.game_id, ge.time
    ) subquery
INNER JOIN games g2
ON g2.id = subquery.game_id
WHERE Rownumber = g2.theirscore + 1

This almost works, the count switches back to 1 when there is a new game_id, but on some games the count start on 9 then move down to 1, instead of starting on 1 and counting upwards.

edit:

solution:

Actually I came up with a solution to this when I was looking through my old bookmarked questions here and here it is (with help from this link: http://www.artfulsoftware.com/infotree/qrytip.php?id=1098 ):

SET @gameprev=0, @gameprev2=0;

SELECT goals.player_id FROM (

SELECT game_id, player_id, time, row_number
FROM 
(
    SELECT player_id, time, @gameprev2 := if(@gameprev = game_id, @gameprev2+1, 1) AS row_number, @gameprev := game_id AS game_id
    FROM gameevents
    WHERE eventtype = 1
    AND thisteam = 1
    ORDER BY game_id, time
    ) as goalorder
) as goals
INNER JOIN games AS g
ON goals.game_id = g.id
WHERE g.ourscore > g.theirscore
AND goals.row_number = g.theirscore +1

Seems MySQL LIMIT doesn't allow dynamic values.

See here.

How to write a SQL query with dynamic LIMIT

Not sure if you can do it in one query and I don't see why you want to do it so. I would first try to load in some table the ordinals which I want and the respective game IDs - say 2 /game 1/, 2 /game 4/, 4 /game 9/.

Then I would use some technique similar to what is mentioned here on the above page.

So I am not sure if you can do it with one old-school query as you call it. You might need a loop, or temp table, or something like that. I am curious myself to figure out how it can be done exactly in the simplest possible way.

Just giving you some directions, hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM