Select max win series: sql query - php

MySQL
I have table, where i store user_matches and it result:
n_match id_user id_score
1 55 1
1 66 0
This mean, 'user with id=55 win match with id=1 to user with id=66'.
So, we have 10, 100, 1000 matches, where user win or lose to opponents:
n_match id_user id_score
1 55 1 (win)
1 66 0
2 55 0 (lose)
2 77 1
3 55 1 (win)
3 77 0
4 55 1 (win)
4 77 0
5 55 1 (win)
5 77 0
Ok. As u can see, user win 3 matches without losing (win series)- and that's what i need from my query.
Question: How could i get from this table the longest series of won matches? Is it possible without looping on sql side or server side- just from query?
Thx.
Edit: One of solution i just now understand,- to get all matches as string like 001010101111010101011, then split it into array of strings with separator '0' -> [1, 1, 1, 1111, ...] and just take the longest string length.
But in this case i have to write server side code =\ That's not good, but mb the fastest.

The best way to do this is to calculate the cumulative number of losses for any match. For a sequence of wins, this value is constant. You can then use group by to get the length of the longest such sequence.
This version of the query is database-neutral. It uses subqueries to get the counts:
select user_id, max(NumWinsInRow)
from (select user_id, cumlosses, count(*)-1 as NumWinsInRow
from (select m.*,
(select sum(case when id_score = 0 then 1 else 0 end) from user_matches m2 where m2.id_user = m.id_user and m2.n_match <= m.n_match
) as CumLosses
from user_matches m
) t
group by cumlosses, user_id
) t
group by user_id
This query should run faster if you have an index on user_matches(id_user, n_math, id_score).

Related

count number of rows associated with their id in another table

Hi We have 3 Table of a music which is something like this in MySql :
1st Table :
the first table is for playlist table where music playlist is exist.
playlistId playlistTitle categoryId
1 hello 0
2 wow 0
3 wi-fi 0
4 awesome 0
5 sixer 1
6 four 1
7 boundary 2
2nd Table :
2nd table is for songRelation table where every playlist is associated with thier song
playlistId songId
1 4
1 3
1 43
1 57
1 98
2 56
2 67
2 90
2 78
3 98
3 78
3 89
43 90
3rd Table : the 3rd table is for song table where song detail exist
songId songTitle
4 hello
3 real hero
43 singalone
57 awesom
98 really
78 sakaka
98 shikwa
89 moha
90 hello2
67 Sneh
actually i am fetching the result something like this:
playlistId songId categoryId songTitle
1 4 0 hello
1 3 0 real hero
2 56 0 singalone
2 67 0 Sneh
3 78 0 sakaka
3 98 0 Shikwa
where the every playlistId will be with their first 2songIdand with theircategoryIdand also withsongTitle`.
but i want to count the total song with every playlistId
after getting the total song result i want will be something like this :
playlistId songId categoryId songTitle totalSong
1 4 0 hello 5
1 3 0 real hero 5
2 56 0 singalone 4
2 67 0 Sneh 4
3 78 0 sakaka 3
3 98 0 Shikwa 3
here is the jsfiddle Demo where query is without totalSong http://sqlfiddle.com/#!9/7eda7/5
What subquery will be added to get the above desired result.
To get exactly the result you asked, use this:
select p.playlistId,
s.songId,
p.categoryId,
s.songTitle,
(select count(*) from songRelation where playlistId = p.playlistId) totalSong
from playlist p
inner join songRelation r on p.playlistId = r.playlistId
inner join song s on r.songId = s.songId
Using a group by on the main query would merge the detailed song data, forcing you to run two queries: one for details (first 4 fields) and a second query, to recover the totals (last column). Using this solution, you get all detailed data and totals, the sub-query will recover the count of songs for each playlist, the way you asked.
UPDATE:
This way, suggested by rlanvin, should make the query faster, because instead on computing the subquery for each row, it gets computed only once, and then is joined to the main query. The result is the same:
select p.playlistId,
s.songId,
p.categoryId,
s.songTitle,
r1.totalSong
from playlist p
inner join songRelation r on p.playlistId = r.playlistId
inner join song s on r.songId = s.songId
inner join (SELECT playlistid, COUNT(songId) as totalSong from songRelation group by playlistid) r1 on p.playlistId = r1.playlistId
I have added this query to ur SQLFIDDLE.
SELECT p.playlistId, s.songId, p.categoryId, s.songTitle,
(select count(sr1.songId) from songRelation sr1
where sr1.playlistid=p.playlistid
group by sr1.playlistId) as total,
#r := IF (#pid = p.playlistId,
IF (#pid := p.playlistId, #r+1, #r+1),
IF (#pid := p.playlistId, 1, 1)) AS rn
FROM playlist AS p
CROSS JOIN (SELECT #r:=0, #pid:=0) AS vars
INNER JOIN songRelation AS sr ON p.playlistId = sr.playlistId
INNER JOIN song AS s ON sr.songid = s.songid
ORDER BY p.playlistId, s.songId ) AS t
WHERE t.rn <= 2
It is giving the required output. Check the Demo Here
Using Group Functions you can do this:
SELECT `playlistid`, COUNT(`songid`)
FROM `playlist`
GROUP BY `playlistid`

get count number of records which respectively exist in another table with null value also

i have two tables. 'listing_messages' and 'listing_message_history'.
listing_messages
=============
message_id listing_id listing_user third_party_user
1 162 7 32
2 162 7 33
3 162 7 12
listing_message_history
======================
listing_message_history message_id is_checked
1 1 0
2 1 1
3 1 1
4 2 0
5 2 1
6 3 0
Search criteria==> listing_user=7, is_checked=1
I want result..
message_id count_of_unread_message_history
12
2 1
3 0
I have made a query is
SELECT count(`lmh`.`message_history_id`) AS COUNT,
`lmh`.`message_id`
FROM `listing_message_history` AS `lmh`
LEFT JOIN `listing_messages` AS `lm` ON `lmh`.`message_id` = `lm`.`message_id`
WHERE `lm`.`third_party_user`=7
AND `lmh`.is_checked=1
GROUP BY `lm`.`message_id`
but it does not returns message_id with count = 0 which message_id do not have is_checked=1
In general, when you use left join, filter conditions on the second table should go in the on clause not the where clause. Try this:
SELECT count(`lmh`.`message_history_id`) AS COUNT,
`lmh`.`message_id`
FROM `listing_message_history` `lmh` LEFT JOIN
`listing_messages` `lm`
ON `lmh`.`message_id` = `lm`.`message_id` AND
`lm`.`third_party_user` = 7
WHERE `lmh`.is_checked = 1
GROUP BY `lmh`.`message_id`;
In addition, you should use the first table for the group by, not the second table.

PHP/MySQL total by member

Like this a result :
75 Ansari 5 10
88 Koodoo 4 0
90 Koodoo 14 0
83 Koodoo 5 0
82 Koodoo, 6 0
81 Koodoo 4 0
79 Koodoo 5 0
74 Savage 1 0
80 Strike 2 36
87 Strike 4 15
78 Sullivan 3 15
77 Sullivan 2 0
I would like to get the total for each member for the last 2 columns (Hours and Minutes).
My query look like that :
SELECT
*
FROM
$tbl_name
ORDER BY
player
If someone would have a quick fix for that I would appreciate it.
Probably you want something like this (but you didn't provide a schema so I'm guessing on the field names).
SELECT `id`, `player`, SUM(`hours`) as hours, SUM(`minutes`) as minutes FROM `$tbl_name` GROUP_BY `player`;
You need to GROUP BY the user's name and SUM the totals for the hours and minutes columns.
A Simple example of this is:
SELECT `id`,
`user`,
SUM(`hours`) as tot_hours,
SUM(`mins`) as tot_mins
FROM `test`
GROUP BY `user`;
You can see this example run at this SQLFiddle
Note: With that fiddle, I removed the extra comma in this line (I assumed it was a typo)
82 Koodoo, 6 0
If that comma is supposed to be there, you just need to adjust that one insert statement to add the comma within the quotes of the name. That will adjust your query outcome as Koodoo, won't group with the other Koodoo values.

Select max difference between 2 rows with the same value (Statistics)

I have a table with some values inserted on a daily basis, something like this
-----------
id | count
-----------
1 | 97
2 | **97**
3 | 59
4 | 62
5 | 47
6 | 59
7 | 59
8 | **97**
-----------
I need to get the max day difference between repeated values, i.e, as you can see the 1st and 2nd value is 97, that is 1 day difference, but the next occurrence of 97 is 6 days later, so I need to get this "Max" difference (6).
same thing for 59, the max day difference is 3 days (3) -- between day 3 and 6.
At this moment I`m using php arrays like this Example:
$q = " SELECT id FROM table WHERE VALUE = 97 ";
// etc ... the array looks like this
$array = {1, 2, 8};
then I get the "Max" difference, but I just want to know if there is any way to do this in mysql, thanks
EDIT:
//if we list only the column "count":
44 5 *97* 74 5 **97** 7 3 2 31 9 8 4 2 1 **97** 4 7 7 8 *97*
step1 : "97" is in 3rd position, then in 6th position (diff = 3)
step2 : "97" is in 6th position, then in 16th position (diff = 10)
step3 : "97" is in 16th position, then in 21st position (diff = 5)
step4 : MAX diff = 10
I must complain about this, I posted this question at 08:59 AM, I reloaded the page 1 minute later (At 9:00) and it was already down-voted, there was no time to read and understand the question, this is absurd
Both work:
http://sqlfiddle.com/#!2/243f2/22
select a.blahday ad, max(b.blahday) bd, a.blahday - max(b.blahday) diff from blah a join blah b using (blahcount)
where blahcount = 97
and a.blahday > b.blahday
group by ad
order by diff desc
limit 1
http://sqlfiddle.com/#!2/243f2/25
select a.blahday ab,
(select max(blahday) from blah where blahcount = a.blahcount and blahday < a.blahday) bd
from blah a
where blahcount = 97
order by ab - bd desc
limit 1
Try this:
select
(`a`.`max_id` - `b`.`min_id`) as `max_day_diff`, `a`.`count`
from
(select max(id) as `max_id`, `count`
from `table` group by `count`
) a
inner join
(select min(id) as `min_id`, `count`
from `table` group by `count`
) b
on `a`.`count` = `b`.`count`
This is the fiddle:
http://sqlfiddle.com/#!2/1a6a3/10
This will give max_day_diff as 0 for rows with only one count value (like 62, 47 in your case)
I think this will get you what you're looking for.
SQLFiddle!
That's a pretty funky table you've got there, btw.

PHP MySQL: Take highest values from multiple categories and write an array?

I have a table of student scores. Students can take the test multiple times, we only care about the highest score.
So the table looks something like this:
UserID CatID Score
20 5 60
20 5 85
20 5 80
20 6 90
20 7 80
20 7 75
20 7 90
22 5 75
22 5 85
Want to get back one row based on a UserID variable that looks like this:
UserID Cat5 Cat6 Cat7
20 85 90 90
Here's what I'm using so far as a query:
SELECT score AS Score
, catid
FROM `quiz_result`
WHERE userid=65 and catid=5
ORDER BY score DESC
LIMIT 0, 1
Not sure how to get the other categories in one row...thoughts?
Thanks!
Try this piece:
SELECT catID, MAX( score ) FROM `quiz_result`
GROUP BY catID;
The output isn't exactly same as in your sample, but it pretty much gives what you need.
EDIT
Output will be like:
catID MAX(score)
Cat5 85
Cat6 90
Cat7 90
To get other columns, just include their names in the SELECT query.
Try this :
SELECT CONCAT_WS(',', catID) AS catID, CONCAT_WS(',', MAX(score)) FROM `quiz_result` GROUP BY catID;

Categories