Calculate net change in ranking after "update", MYSQL - php

I have a two MYSQL tables:
Table-1
id catid title user_rating
123 8 title-one 3
321 8 title-two 5
and
Table-2
listing_id title user_rating
123 title-one 3
321 title-two 5
Plus, I have this query that calculates the current rank of each "title" based on "user_rating".
SELECT
MAX(x.rank) AS rank
FROM
(SELECT
a.id,
a.catid,
a.title,
b.listing_id,
#rank:=#rank + 1 AS rank
FROM
`table-1` a
INNER JOIN `table-2` b ON a.id = b.listing_id
CROSS JOIN (SELECT #rank:=0) r
WHERE
catid = '8'
ORDER BY user_rating DESC) x
WHERE
id = 123
Now, my issue: I want to calculate the difference in "ranking" (rank) when I update the "user_rating" value.
Please, note: the "user_rating" value is updated by a php script that allow users to vote for a specific content (range 1 to 5, step 0.5).
What's the best way to get the difference between the "previous rank" and "current rank" after the update?
Thanks in advance to all.

Related

MySql get row if id is in sequence

We require to get row if product_id is in sequence.
Table (product)
product_id name
1 Parle
2 Coconut
3 Pizza
4 Colgate
5 Ice Cream
6 Nuts
8 Britania
9 Pepsi
Require Output
product_id name
1 Parle
2 Coconut
3 Pizza
4 Colgate
5 Ice Cream
6 Nuts
product_id - 8 and 9 not getting because it is not in sequence.
My Try
select distinct t1.*, t1.product_id, (select GROUP_CONCAT(t2.product_id) from product as t2) as p_id
from product t1
having FIND_IN_SET(t1.product_id+1, p_id)
Output
product_id name
1 Parle
2 Coconut
3 Pizza
4 Colgate
5 Ice Cream
In this try i am not getting product_id - 6 row.
Note : I want MySql query not in PHP.
Thank You !
One way i can think of is to user user defined variable to get the rank of row and then calculate the difference of product id and rank and select only those rows where difference = 0
select *
from(
select f.*,#row:= #row + 1 rank,
product_id - #row as diff
from product f,
(select #row:= 0) t
order by product_id
) t1
where diff = 0
Demo
Or if you want to pick the least sequence no. automatically you can write it as
select *
from(
select f.*,#row:= #row + 1 rank,
product_id - #row as diff
from product f,
(select #row:= (select min(product_id) from product_sale_flag) a) t
order by product_id
) t1
where diff = -1
Demo
Explanation
First query assign's minimum value of product_id to variable #row,then it assigns a rank to each row ordered by product_id in ascending order, once rank is assigned for every row then it calculates the difference between the original value of product_id and lastly using the resultant difference it checks where difference is 0 get those rows because they follow the sequence. Hope this makes sense

How to count best ranks for each user from one tabel and Insert/Update with results another table [duplicate]

This question already has answers here:
MySQL query to get best Ranks from one table and UPDATE with results another
(2 answers)
Closed 4 years ago.
I have a Ranking board for the best first 100 blogs for each gender Males and Females.
I have a blogs table:
PRIMARY
blogs_id users_id blogs_score blogs_score_time gender
1 11 2852 2015-09-09 05:21:51 m <-- same score but older date
2 23 2146 2015-09-10 07:31:54 m
3 23 2146 2015-09-10 07:32:26 m
4 23 2852 2015-09-10 04:42:15 m <-- same score but newer date
5 51 1793 2015-09-11 08:15:55 f
6 88 2947 2015-09-11 09:33:18 f
I have a users table:
PRIMARY
id best_rank gender
11 0 m
23 0 m
51 0 f
88 0 f
I need to COUNT best ranks (using MAX(blogs_score) and MAX(blogs_score_time)) for each user from Blogs table and INSERT/UPDATE the Users table with the best ranks for the first 100 users of each gender with highest ranks, so the result should be:
PRIMARY
id best_rank gender
11 2 m
23 1 m
51 2 f
88 1 f
The Best Ranks supposed to be for each gender.
The final idea is to show the Rank position in user's profile and once someone voted (blogs_score changes in the blogs table), the best_rank column in the users table must be updated with the new ranks recalculation for ALL 100 users who has the best ranks in particular gender group.
How to adapt and fix this (not working) query to my needs?
$sql->query("UPDATE users
JOIN (SELECT b.users_id,
#curRank := #curRank + 1 AS rank,
MAX(blogs_score), MAX(blogs_score_time)
FROM blogs b
JOIN (SELECT #curRank := 0) r
ORDER BY b.blogs_score DESC, p.blogs_score_time DESC LIMIT 100
) ranks ON (ranks.users_id = users.id)
SET users.best_rank = ranks.rank");
Please help me with the query to solve it. I didn't find any similar solution on stackoverflow and it seems very complicated for me to write such a query alone.
Thanks a lot in advance!
To come up with your desired results I would use the following:
SELECT users_id, MAX(blogs_score), gender
FROM blogs
GROUP BY users_id, gender
ORDER BY blogs_score_time DESC
Result:
users_id MAX(blogs_score) gender
88 2947 f <-- first F
51 1793 f <-- second F
23 2852 m <-- first M
11 2852 m <-- second M
Okay... Here's my latest :)
I don't know how you want to use the date field, but would row_number with a partition do what you need to do?
declare #blogs table (blogs_id int, users_id int, blogs_score int, blogs_score_time datetime, gender char(1))
insert #blogs
select 1, 11, 2852, '2015-09-09 5:21:51', 'm'
union all
select 2, 23, 2146, '2015-09-10 7:31:54', 'm'
union all
select 3, 23, 2146, '2015-09-10 7:32:26', 'm'
union all
select 4, 23, 2852, '2015-09-10 4:42:15', 'm'
union all
select 5, 51, 1793, '2015-09-11 8:15:55', 'f'
union all
select 6, 88, 2947, '2015-09-11 9:33:18', 'f'
select top 100
row_number() OVER(PARTITION BY GENDER ORDER BY BLOGS_SCORE DESC) [Rank],
*
from #blogs
order by blogs_score desc, blogs_score_time desc

Need hint with MySQL query from 2 Tables

I need a small hint... I've got 2 Tables.
Table 1 gets data from an external api.
Table 2 is static.
Table 1: data
id name status ratio import_id
1 Test online 3 1
2 Tee online 2 1
3 Test online 1 2
4 Tee online 0.01 2
5 Test offline 4 3
6 Teee online 3 3
7 Teet online 1 3
Table 2: names
id name tag active
1 Test t1 1
2 Tee t2 1
3 Teee t3 0
4 Teet t4 1
I want to have the ID from the table names (to write into another table and execute a cronjob)
Explanation Table 1:
id - AI
name - just the name
status - if the entry is active
ratio - the main select
import_id - every 10 minutes I do import from json (~40 entries)
what i've got:
$result = mysql_query("
SELECT
import_id
FROM
data
ORDER BY id DESC LIMIT 1");
while($raw = mysql_fetch_object($result))
{
$the_id = $raw->import_id;
echo $the_id;
}
Now I've got the ID and try to get the latest entry (import_id) with the highest ratio:
$c_result = mysql_query("
SELECT
name, active, ratio, import_id
FROM
data
WHERE
active = '1' AND import_id = '$the_id'
ORDER BY
ratio DESC LIMIT 1");
while($chosen = mysql_fetch_object($c_result))
{
$the_c = $chosen->name;
echo $the_c;
}
That works flawless.
But it is possible that one of the 40 entries provided by api is not in my table "names" or it is not marked as "active".
But I only want the names.id of
the name with the highest ratio
which is in my table "names"
which is marked as active in "names"
and the data.status is online
which is from the latest import (highest import_id)
and write it to another table.
I thought about a LEFT JOIN but if the names.name is not in the table "names" i just get an empty result.
Have you got a hint in the right direction?
SELECT d.name, active, ratio, import_id
FROM data d
JOIN names n ON d.name = n.name
WHERE import_id = (SELECT import_id
FROM data
ORDER BY id DESC
LIMIT 1)
AND d.status = 'online'
AND n.active = 1
ORDER BY ratio DESC
LIMIT 1
DEMO

Mysql select max maximum sum values

I have a database which contains some picture data and a linking table. The tables are build-up like this:
---pictures---
picid Lat Lon
1 5 6
2 7 31
3 31 43
4 -3 35
---user2pictures---
picid userid vote
1 1 1
1 2 1
3 1 -1
3 2 1
4 2 -1
The table pictures contains a picture id and some data about the image, the table user2votes contains vote data from the images. Each user is able to vote on images, but they can only vote 1 time, so the vote will be either 1 (like) or -1 (dislike).
I want to select everything from the pictures table from pictures which have the highest number of votes. Pseudoquery which might explain better what I want:
SELECT * FROM pictures WHERE (SELECT MAX(SUM(vote)) FROM user2pictures LIMIT 12
In this example picture 1 would return at the top, picture 3 would follow and picture 4 as the last one. I really don't know how to solve this, some help in the right direction would be very much appreciated!
Thanks!
The answer is to JOIN the tables, SUM the votes, and ORDER high-to-low by the sum of the votes
SELECT pictures.*, SUM(user2pictures.vote) AS VoteTotal
FROM pictures
JOIN user2pictures ON pictures.picid = user2pictures.picid
GROUP BY pictures.picid
ORDER BY VoteTotal DESC
LIMIT 12
try this
select p.`picid`, `Lat`, `Lon` from pictures p
inner join user2pictures u2p
on p.picid = u2p.picid
group by u2p.picid
order by sum(vote) desc
limit 12
DEMO
I'll assume that you also want to show the pictures with no votes. So, you can try this:
select
p.picId, sum(v.vote) as votes
from
pictures as p
left join user2pictures as v on p.picId = v.picId
group by
p.picId
order by
sum(v.vote) desc
limit 12;
The left join is what lets you show the pictures with no votes (the column votes will have the value 0)
Hope this helps

get SUM of another row of GROUP BY'd rows

I have this table:
This selection is is duplicated many times for different var_lines (which pretty much work as one row of data, or respondent for a survey) and set_codes (different survey codes).
With this query:
SELECT
*, COUNT(*) AS total
FROM
`data`
WHERE
`var_name` = 'GND.NEWS.INT'
AND(
`set_code` = 'BAN11A-GND'
OR `set_code` = 'BAN09A-GND'
OR `set_code` = 'ALG11A-GND'
)
AND `country_id` = '5'
GROUP BY
`data_content`,
`set_code`
ORDER BY
`set_code`,
`data_content`
The query basically counts the number of answers for a specific question. Then groups them survey (set_code).
What I need is for each of the grouped data_content answers for GND.NEWS.INT to also show the SUM of all the corresponding GND_WT with the same var_line.
For example if I had this:
data_id data_content var_name var_line
1 2 GND.NEW.INT 1
2 1.4 GND_WT 1
3 2 GND.NEW.INT 2
4 1.6 GND_WT 2
5 3 GND.NEW.INT 3
6 0.6 GND_WT 3
I would get something like this:
data_id data_content var_name var_line total weight
1 2 GND.NEW.INT 1 2 3
5 3 GND.NEW.INT 3 1 0.6
Thanks for any help.
Your requirements are not exactly clear, but I think the following gives you what you want:
select d1.data_id,
d1.data_content,
d1.var_name,
d1.var_line,
t.total,
w.weight
from data d1
inner join
(
select data_content,
count(data_content) Total
from data
group by data_content
) t
on d1.data_content = t.data_content
inner join
(
select var_line,
sum(case when var_name = 'GND_WT' then data_content end) weight
from data
group by var_line
) w
on d1.var_line = w.var_line
where d1.var_name = 'GND.NEW.INT'
See SQL Fiddle with Demo
This Query can be suitable for your specific example:
select st.data_id,
st.data_content,
st.var_name,
st.var_line,
count(st.data_id) as total,
sum(st1.data_content) as weight
from data st
left join data st1 on st1.var_name = 'GND_WT' AND st1.var_line=st.var_line
where st.var_name='GND.NEW.INT'
group by st.data_content
Regards,
Luis.

Categories