need help with complex sql statement

theGlove

Senior member
Jan 13, 2005
884
0
0

I'm trying to form an sql statement to compute the kill/death ratio of players that I am keeping stats for.

the database table has the following columns:

UserData Table: userName, defeatedName, location, killDate


sample data for the table:

http://i5.photobucket.com/albu...love113/sampledata.jpg

basically, 'userName' is the person who killed 'defeatedName'.



I have a sql query that computes the top 20 users with most kills as:

SELECT userName, count(userName),
FROM UserData
WHERE killDate > DATE_SUB(now(),
INTERVAL 1 HOUR)
Group By userName
order by count(userName)
DESC limit 20;


but I can't figure out how to compute the top 20 users with the best kill ratio.
I'm thinking I should right a stored procedure to do this but I think there should be
an sql query that can do this?




 

brandonb

Diamond Member
Oct 17, 2006
3,731
2
0
select top 20 "kills", k.username
from (
select username, count(username) as count
from table
group by username
) as k
order by k.count DESC

UNION

select top 20 "deaths", d.defeatedName
from (
select defeatedName, count(defeatedName) as count
from table
group by defeatedName
) as d
order by d.count DESC

----

Thats where I'd start, I havent debugged it but thats what comes to mind.

If you just want ratio

select top 20 "killratio", kr.username, kr.ratio
from (

select username, cast((r.kills / r.deaths) as numeric(18,6)) as ratio
from
(

select username, count(username) as kills, d.deaths
from table
Inner join (

select defeatedName, count(defeatedName) as deaths
from table
group by defeatedName ) as d on table.username =d.username
group by username
) as r
) as kr
order by kr.count DESC

Sorry about the formatting, its hard to read I know. But you just do seperate queries, one for kills, one for deaths, group them together as a ratio, then pick out the 20 top ones. That statement won't really work as is, but I think I'm on the right path.
 

drebo

Diamond Member
Feb 24, 2006
7,034
1
81
Sometimes it's OK to break 3rd normal form for the sake of simplicity in situations exactly like this.

Instead of counting how many kills a person has every time they look at their tally (that can be REALLY slow if your dataset gets big), simply include a counter for kills and deaths in the main user table.

Is it 3rd normal form? Not quite, there's some repetition in the data. But, it's a sacrifice that will increase the efficiency and speed of reports which use those values.
 

theGlove

Senior member
Jan 13, 2005
884
0
0
thanks all for the help, you guys are good i'm gonna try out the sql that brandonb has written and see the performance i get
with that. since the table is fairly large 50k+ rows, i might have to create additional tables as suggested. thanks
 

nakedfrog

No Lifer
Apr 3, 2001
59,258
13,875
136
Originally posted by: Train
you could just write a trigger to update a ratio column on any update?

that way all ratios are always up to date

That seems to me like it result in an excessive amount of overhead.

Does MySQL support calculated fields?
 

Train

Lifer
Jun 22, 2000
13,572
66
91
www.bing.com
Originally posted by: nakedfrog
Originally posted by: Train
you could just write a trigger to update a ratio column on any update?

that way all ratios are always up to date

That seems to me like it result in an excessive amount of overhead.

Does MySQL support calculated fields?

Less overhead than computing the whole table on each select then sorting them all to grab the top 20.

With a trigger only affected records get recalculated, instead of the entire table. Would make the select statment he's looking for much faster.

 

brandonb

Diamond Member
Oct 17, 2006
3,731
2
0
Nice job on getting my query to work. ha ha.

I noticed that you can probably combine the sub query for kills + deaths to the ratio one so you can remove that nested SQL there. It would probably speed it up somewhat. Give it a shot.

Just move the:

select username, cast((r.kills / r.deaths) as numeric(18,6)) as ratio

to the select statement below like:

select username, count(username) as kills, d.deaths, count(r.kills) / r.death as ratio

and reduce the nested SQL by one level there.

I don't know if it will work, but you can play around with doing things like that to see if it helps or not with performance and readability.
 
sale-70-410-exam    | Exam-200-125-pdf    | we-sale-70-410-exam    | hot-sale-70-410-exam    | Latest-exam-700-603-Dumps    | Dumps-98-363-exams-date    | Certs-200-125-date    | Dumps-300-075-exams-date    | hot-sale-book-C8010-726-book    | Hot-Sale-200-310-Exam    | Exam-Description-200-310-dumps?    | hot-sale-book-200-125-book    | Latest-Updated-300-209-Exam    | Dumps-210-260-exams-date    | Download-200-125-Exam-PDF    | Exam-Description-300-101-dumps    | Certs-300-101-date    | Hot-Sale-300-075-Exam    | Latest-exam-200-125-Dumps    | Exam-Description-200-125-dumps    | Latest-Updated-300-075-Exam    | hot-sale-book-210-260-book    | Dumps-200-901-exams-date    | Certs-200-901-date    | Latest-exam-1Z0-062-Dumps    | Hot-Sale-1Z0-062-Exam    | Certs-CSSLP-date    | 100%-Pass-70-383-Exams    | Latest-JN0-360-real-exam-questions    | 100%-Pass-4A0-100-Real-Exam-Questions    | Dumps-300-135-exams-date    | Passed-200-105-Tech-Exams    | Latest-Updated-200-310-Exam    | Download-300-070-Exam-PDF    | Hot-Sale-JN0-360-Exam    | 100%-Pass-JN0-360-Exams    | 100%-Pass-JN0-360-Real-Exam-Questions    | Dumps-JN0-360-exams-date    | Exam-Description-1Z0-876-dumps    | Latest-exam-1Z0-876-Dumps    | Dumps-HPE0-Y53-exams-date    | 2017-Latest-HPE0-Y53-Exam    | 100%-Pass-HPE0-Y53-Real-Exam-Questions    | Pass-4A0-100-Exam    | Latest-4A0-100-Questions    | Dumps-98-365-exams-date    | 2017-Latest-98-365-Exam    | 100%-Pass-VCS-254-Exams    | 2017-Latest-VCS-273-Exam    | Dumps-200-355-exams-date    | 2017-Latest-300-320-Exam    | Pass-300-101-Exam    | 100%-Pass-300-115-Exams    |
http://www.portvapes.co.uk/    | http://www.portvapes.co.uk/    |