Calculating ranks from the following data [duplicate] - mysql

This question already has answers here:
Rank function in MySQL
(13 answers)
Closed 8 years ago.
How can I calculate the rank for all "type 10" rows in the data below using just sql?
The sql will go into a stored procedure, with no other scripting involved.
The parent holds the total of all rows in column total, and the total votes in votes.
I update the perCent col using this, so this should give you an idea. Maybe calculate ranks along with this?
All rows are linked by parent -> child relationship.
All is based on total votes and total candidates. Candidates are type 10
UPDATE likesd p
JOIN likesd h
ON p.parent = h.id
AND p.country = h.country
SET p.percent = TRUNCATE(100*p.votes/h.votes,2);
Raw Data
"id" "type" "parent" "country" "votes" "perCent" "total" "rank"
"24" "1" "1" "US" "30" "0" "" "0"
"25" "3" "24" "US" "30" "0" "3" "0"
"26" "10" "25" "US" "15" "50.00" "" "0"
"27" "10" "25" "US" "5" "16.66" "" "0"
"28" "10" "25" "US" "10" "33.33" "" "0"
Desired results
"id" "type" "parent" "country" "votes" "perCent" "total" "rank"
"24" "1" "1" "US" "30" "0" "" "0"
"25" "3" "24" "US" "30" "0" "3" "0"
"26" "10" "25" "US" "15" "50.00" "" "1" // Rank 1. Has 15 votes out of 30 (see parent row above)
"27" "10" "25" "US" "5" "16.66" "" "3" // And so on.
"28" "10" "25" "US" "10" "33.33" "" "2"

SELECT id,type,parent,country,votes,perCent,total, FIND_IN_SET( votes, (
SELECT GROUP_CONCAT( votes
ORDER BY votes DESC )
FROM table WHERE type=10 )
) AS rank
FROM table
SQL Fiddle
SQL Fiddle
UPDATE scores SET rank= (FIND_IN_SET(votes, (
SELECT * FROM(SELECT GROUP_CONCAT( votes
ORDER BY votes DESC )
FROM scores WHERE type=10)x ) ) )

Related

MySql combining update with an inner join and limit

I'm trying to update a row in table amga with just one row from table amgb joined by their itemTempId.
My problem is that, there may be upto 6 rows in table amgb for that itemTempIdand I need to use only one from it for the update.
I'm familiar with doing updates with joins, but when I added a Limit (so as to get just one row) I get the error message Incorrect usage of update and limit. I read that this is not possible, but would there be another way to do this?
amga
"id" "itemId" "itemTempId" "itemImageName" "itemName" "itemCountry" "userId"
"1" "US1" "T001" \N "Samsung Galaxy Note 5" "US" "1"
"2" "CA2" "T002" \N "Samsung Galaxy Note 6" "CA" "2"
"3" "UK3" "T003" \N "Samsung Galaxy Note 7" "UK" "3"
amgb
"id" "itemId" "itemTempId" "itemImageName" "userId"
"1" "US1" "T001" "front.jpg" "1"
"2" "US1" "T001" "side-left.jpg" "1"
"3" "US1" "T001" "side-right.jpg" "1"
"4" "US1" "T001" "back.jpg" "1"
"5" "CA2" "T002" "front.jpg" "2"
"6" "CA2" "T002" "side-left.jpg" "2"
"7" "CA2" "T002" "side-right.jpg" "2"
"8" "CA2" "T002" "back.jpg" "2"
"9" "UK3" "T003" "front.jpg" "3"
Sql I used
update amga a inner join amgb b on a.itemTempId = b.itemTempId
set a.itemImageName = b.itemImageName where a.itemTempId = 'T001' limit 1;
Expected results: Table amga after update
"id" "itemId" "itemTempId" "itemImageName" "itemName" "itemCountry" "userId"
"1" "US1" "T001" front.jpg "Samsung Galaxy Note 5" "US" "1"
"2" "CA2" "T002" \N "Samsung Galaxy Note 6" "CA" "2"
"3" "UK3" "T003" \N "Samsung Galaxy Note 7" "UK" "3"
Note: itemTempId is updated with front.jpg, which is the first row for itemTempId = T001 in amgb
Any help appreciated.
Update
I noticed it works if I remove the limit, and that it updates too. But is it the right way to do it? What does MySql do with the other rows in the select?
update amga a inner join amgb b on a.itemTempId = b.itemTempId
set a.itemImageName = b.itemImageName where a.itemTempId = 'T001';
Maybe you can use a subquery:
UPDATE amga a
SET a.itemImageName =
(SELECT b.itemImageName
FROM amgb b
WHERE b.itemTempId = 'T001'
ORDER BY b.id LIMIT 1)
WHERE a.itemTempId = 'T001'

Mysql stuck with order by desc and limit

I have a table like this:
"id" "UserName" "score"
"1" "User 1" "2"
"2" "User 2" "5"
"3" "User 3" "3"
"4" "User 4" "7"
"5" "User 5" "1"
and run an sql like this:
select userName from stack where id >= 0 order by score DESC LIMIT 3
That gives me the result
"userName"
"User 4"
"User 2"
"User 3"
Which means its arranged like this this;
"id" "UserName" "score"
"4" "User 4" "7"
"2" "User 2" "5"
"3" "User 3" "3"
"1" "User 1" "2"
"5" "User 5" "1"
How can I start at id 1 and get results as below. Because no matter what I do, I keep getting incorrect results:
Expected results:
select userName from stack where id >= 1 order by score DESC LIMIT 3
"1" "User 1" "2" /*These are my expected results and not what the above query outputs*/
"5" "User 5" "1"
This whole thing comes from a pagination system where we use to display users based on their scores.
You can use an offset in the LIMIT:
select userName from stack where id >= 1 order by score DESC LIMIT 3,3
For your pagination you have to increase your offset for every page.

Select Users who have made the most positive contributions

I thought I had this, but it's clear I don't. From the table below, I'm trying to display users who have made the most positive contributions (articles) on top, followed by the ones who didn't. The table is simple, artc_id is the article Id, artc_status is the status which shows if an article was approved or not. 0 is approved, 1 is not, then comes the user who wrote the article.
The results I'm trying to achieve are as follows:
Total Contributions Positive Contributing User
4 4 2
3 2 1
1 1 4
3 0 3
Table
"id" "artc_id" "artc_status" "artc_user" "artc_country"
"1" "1" "0" "1" "US"
"2" "2" "0" "1" "US"
"3" "3" "1" "1" "US"
"4" "4" "0" "2" "US"
"5" "5" "0" "2" "US"
"6" "6" "0" "2" "US"
"7" "7" "0" "2" "US"
"8" "8" "1" "3" "US"
"9" "9" "1" "3" "US"
"10" "10" "1" "3" "US"
"11" "11" "0" "4" "US"
The Sql I came up with
select count(artc_status) as stats , artc_user from contributions where artc_status = 0 group by artc_user order by stats desc;
I'm not having much luck getting results like I posted above. Can you please assist? This is completely beyond me.
select
count(artc_status) as stats ,
count(case when artc_status=1 then 1 end) Positive,
artc_user[Contributing User]
from
contributions
group by
artc_user
order by stats desc;
I think you just need conditional aggregation to get the two summary columns:
select count(*) as TotalContributions, count(artc_status = 0) as PositiveContributions, artc_user
from contributions
group by artc_user
order by PositiveContributions desc;

Combining two select SQL queries into one

"id" "type" "parent" "country" "votes" "perCent"
"1" "1" "0" "US" "0" "0"
"2" "3" "1" "US" "105" "0"// Total
"3" "10" "2" "US" "15" "0"
"4" "10" "2" "US" "50" "0"
"5" "10" "2" "US" "25" "0"
"6" "10" "2" "US" "5" "0"
"7" "10" "2" "US" "10" "0"
"8" "1" "0" "US" "0" "0"
"9" "3" "8" "US" "80" "0"// Total
"10" "10" "9" "US" "10" "0"
"11" "10" "9" "US" "5" "0"
"12" "10" "9" "US" "15" "0"
"13" "10" "9" "US" "20" "0"
"14" "10" "9" "US" "30" "0"
In the above table likes, I have the total votes stored in a type = 3 row.
I'm trying to update the perCent column with the percentage of votes each has got where type = 10.
I do this right now in php like below. Can the first two statements be combined into one? I lost trying with joins and inner joins etc.
The way I currently do things in php is as follows:
select id, votes as totalVotes from likes where type = 3 and country = 'us';
select votes from likes where parent = id and type = 10;
update votes set votes = (100*10/totalVotes) where type = 10 and parent = id;
Results I trying to achieve:
"id" "type" "parent" "country" "votes" "perCent"
"1" "1" "0" "US" "0" "0"
"2" "3" "1" "US" "105" "0"// Total
"3" "10" "2" "US" "15" "14.28" (100*15/105)
"4" "10" "2" "US" "50" "47.61"
"5" "10" "2" "US" "25" "23.80"
"6" "10" "2" "US" "5" "4.76"
"7" "10" "2" "US" "10" "9.53"
"8" "1" "0" "US" "0" "0"
"9" "3" "8" "US" "80" "0"// Total
"10" "10" "9" "US" "10" "12.5"
"11" "10" "9" "US" "5" "6.25"
"12" "10" "9" "US" "15" "18.75"
"13" "10" "9" "US" "20" "25.00"
"14" "10" "9" "US" "30" "37.50"
This should do what you're asking, updating all products' percentages to reflect their part of the total votes under their heading;
UPDATE likes p
JOIN likes h
ON p.parent = h.id
AND p.type=10 AND h.type=3
AND h.country = 'US'
SET p.percent=100*p.votes/h.votes;
An SQLfiddle to test with.
Check SQLFiddle .
UPDATE `votestable` v
SET v.`percent` = (SELECT
ROUND( ( ( v.votes * 100) / v1.votes ), 2 )
FROM (SELECT
votes,
id
FROM Votestable) AS v1
WHERE v1.id = v.parent)
If I'm not mistaken, this looks like a left join to me.
SELECT lp.id, lp.votes + COALESCE(SUM(lc.votes), 0) as totalVotes FROM likes lp
LEFT JOIN likes lc ON lc.parent = lp.id AND lc.type = 10
WHERE lp.type = 3 AND lp.country = 'us'

Selecting table using case clause in from clause

I have 8 table that contain different specific value for computer peripheral they are glpi_device_ram, glpi_device_hdd, glpi_device_gfxcard, glpi_device_sndcard. Each table has the same designation column in each table that contain device name. i have table glpi_computer_device that contain FK_device that contain id for each 8 table above and device type column that help me decide which table(from 8 table above) should i associate with FK_device to get designation column. I have create sql syntax but not work. I need to know whether selecting table in FROM clause using CASE clause is allowed? Here is my code
SELECT CASE device_type
WHEN "1" THEN "Casing"
WHEN "2" THEN "Processor"
WHEN "3" THEN "RAM"
WHEN "4" THEN "Harddisk"
WHEN "5" THEN "Network Card"
WHEN "6" THEN "Drive"
WHEN "7" THEN "UNKNOWN"
WHEN "8" THEN "Graphic Card"
WHEN "9" THEN "Sound Card"
WHEN "10" THEN "Other device"
END AS devicetype,
CASE device_type
WHEN "1" THEN "--"
WHEN "2" THEN "Frequency"
WHEN "3" THEN "Size"
WHEN "4" THEN "Capacity"
WHEN "5" THEN "Mac Address"
WHEN "6" THEN "Memory Size"
WHEN "7" THEN "--"
WHEN "8" THEN "Memory Size"
WHEN "9" THEN "--"
WHEN "10" THEN "--"
END AS secificity_type,
specificity,
(SELECT c.designation
FROM (SELECT CASE cd.device_type
WHEN "2" THEN "glpi_device_processor"
WHEN "3" THEN "glpi_device_ram"
WHEN "4" THEN "glpi_device_hdd"
WHEN "5" THEN "glpi_device_iface"
WHEN "6" THEN "glpi_device_drive"
WHEN "8" THEN "glpi_device_gfxcard"
WHEN "9" THEN "glpi_device_sndcard"
WHEN "10" THEN "glpi_device_pci"
END
FROM glpi_computer_device cd
WHERE cd.ID = ID ) AS c
WHERE c.ID=FK_device)
FROM `glpi_computer_device`
WHERE FK_computers = 1
no that does not work.
you should structure this as a UNION of all 8 tables - then wrap that with another select statement to get the value.