Using php and Mysql to Order by highest number and confirmation - php

Well I have this mysql table with numbers in one column and a confirmation boolean of 0 or 1 and I have about 1,000 rows so it's not something I can do manually but anyways...
I want to sort the row by highest value and grab the names of the first 5 people and put those 5 people in another table on a column and then set them to confirmed and continue until there's no one left in the table that isn't confirmed...
ex:
Name:Rank:Confirm
Bob:5000:0
James:34:0
Josh:59:1
Alex:48:0
Romney:500:0
Rolf:24:0
Hat:51:0
so when you run the code it will do the following:
Squad:Name1:Name2:Name3:Name4:Name5
1:Bob:Romney:Hat:Alex:James
(as you can see Josh was excluded and Rolf was too low)
And since Rolf is alone and there are no one else left, he wont be put into a team and will be left unconfirmed...
I'm not really pro at mysql so I was stumped on this and at most was capable of organizing the whole thing by rank and that's it ._.
edit:
The terrible attempt I had at this:
<?php
$parse = mysql_query("SELECT MAX(rank) AS rank FROM users AND confirm='0'");
mysql_query("Insert into squad (nameone)values($parse)");
mysql_query("Update squad set confirm = '1' where name = $parse");
?>

Assuming confirm will have only either 1 or 0.
CREATE TABLE table2 (id INT PRIMARY KEY AUTO_INCREMENT, name varchar(255));
CREATE PROCEDURE rank()
BEGIN
DECLARE count INT DEFAULT 1;
WHILE count > 0 DO
UPDATE table1 SET Confirm=2 WHERE Confirm=0 ORDER BY Rank DESC LIMIT 5;
INSERT INTO table2 (SELECT GROUP_CONCAT(Name) FROM table1 WHERE Confirm=2);
UPDATE table1 SET Confirm=1 WHERE Confirm=2;
SELECT count(*) FROM table1 WHERE Confirm=0;
END WHILE;
END;
Call the procedure rank() when ever you want
CALL rank();

Related

Mysql delete all except 100 new rows

Hello I need to empty all table except the x new rows i have already test
How to delete all rows from a table except newest 10 rows
SQL Delete all rows except for last 100
But not work, my mysql version doesn't support limit "IN"
(actual version Ver 14.14 Distrib 5.5.46)
My table is like that
ID (int)
DATE (timestamp)
Who i can empty without loop ? Thanks
Try this
<?php
$mysqli=new mysqli("localhost", "root", "", "db");
$result=$mysqli->query("select id from tabl order by id desc" );
$res=$result->fetch_array();
echo $res[0];
$id=$res[0]-100;
$mysqli->query("delete from table where id < $id");
?>
You can do it with a single SQL DELETE statement that uses variables:
DELETE mytable
FROM mytable
INNER JOIN (
SELECT ID, #rn := #rn + 1 AS rn
FROM mytable
CROSS JOIN (SELECT #rn := 0) AS var
ORDER BY DATE DESC
) AS t ON mytable.ID = t.ID
AND t.rn > 100
The derived tasble t is used to assign each ID of mytable a row number. Numbering uses ORDER BY DATE DESC, hence 100 most recent records are going to have rn in [1-100]. DELETE removes any row of mytable except those having rn in [1-100].
Demo here (Demo keeps 10 more recent records instead of 100)
You can do it by using number of SQL statments one after another.
You can do it by get the first ID that you want to delete, and then delete all the rows newer that ID
// Create the memory table for storing the IDs
create table mem(
first100 integer
);
// Insert to the memory table the list of 100 last ids
insert into mem(first100) select id from table order by id desc limit 100;
// Insert to Mysql variable #a, the id of the first id to delete
set #a=select fist100 from mem order by id limit 1;
// Delete all the id's after the one you want to delete
delete from table where id>=#a
Update:
I posted this answer befor you wroted that the error message is: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME
Anyway, I keep it, maybe this method will help to someone else .

Finding the latest updated value only from table

Hey guys i have a table structure like
CREATE TABLE CUSTOMERS(
ID INT NOT NULL,
NAME VARCHAR (20) NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR (25) ,
SALARY DECIMAL (18, 2),
PRIMARY KEY (ID)
)
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (1,'aff',2,3,5)
VALUES (2,'afff',1,31,52)
update CUSTOMERS
set NAME = 'somenewname'
where age = 1;
I just want to get output as 'somename'
I have tried creating a column updatedtime with timestamp and used query like
SELECT * FROM CUSTOMERS ORDER BY updatetime DESC LIMIT 1;
But this one shows the whole values ..
I just need only the updated value 'somenewname` as output.
I have also tried using triggers and functions but it didnt helped..
Please help me with a solution..I will accept it as an answer if it helps me ..remember i want an output as a single value like somenewname.
Thanx
The trigger which i have used
CREATE TRIGGER getrandom
AFTER UPDATE ON CUSTOMERS
FOR EACH ROW
BEGIN
UPDATE CUSTOMERS
SET NAME = 'anewname'
WHERE ADDRESS = 3;
END;
Why don't you try to SELECT only the name-column
SELECT name FROM CUSTOMERS ORDER BY updatetime DESC LIMIT 1; //outputs the name
instead of the whole result
SELECT * FROM CUSTOMERS ORDER BY updatetime DESC LIMIT 1;
Your UPDATE statement should look like
update CUSTOMERS
set NAME = 'somenewname',
updatetime = now()
where age = 1;
Now a example of how to get only the name if tables are joined.
SELECT c.name FROM CUSTOMERS as c INNER JOIN orders as o c.id=o.id ORDER BY c.updatetime DESC LIMIT 1;

Want to delete any unique userid has more than 50 items

I have a table with named "user-recent-activity" which has following columns: id, userid, activity and datetime. Now, I want to delete the records if any unique userid has more than 50 items, deleting the oldest records. For example, if the user id(lets say 1234) has more than 50 records in this table, then I have to save latest 50 records of user id(1234) and delete the oldest one.
Before inserting, query for the last 50 records with that ID (ordering from newer to older). If there is a 50th, substitute it (via update) instead of inserting a new row.
Assuming you are using a RDBMS that supports standard SQL the following stored procedure should do it.
create procedure remove-old-activities
(
#userid int
)
as
delete from user-recent-activity where userid=#userid and id not in (select top 50 id from user-recent-activity where userid=#userid order by datetime desc)
If you're DB does not support stored procedures then you should be able to use SQL parameters to pass the userid value...
Hope that helps
You could use rank method to precisely defined the rows number and thus delete the rows you want.
delete from tblName where id=
(select id from (
select #i := CASE WHEN ( #userid <> userid ) THEN 1
ELSE #i+1
END AS rank , id,userid, datetime2 ,#userid:=userid AS clset
from tblName x,(SELECT #i:=0) a ,(SELECT #userid:= 0) s
order by x.userid, datetime2 desc) T
where T.rank='50') ;
Another option:
Use the select query to select the rank <=50 and insert into a new table. Delete the old table and rename the new table afterwards.
insert into newtable (userid,activity,datetime2)
select userid,datetime2 from (
select #i := CASE WHEN ( #userid <> userid ) THEN 1
ELSE
#i+1
END AS rank , userid, activity,datetime2 ,#userid:=userid AS clset
from tblName x,(SELECT #i:=0) a ,(SELECT #userid:= 0) s
order by x.userid, datetime2 desc) T
where t.rank <=50

SQL position of row(ranking system) WITHOUT same rank for two records

so I'm trying to create a ranking system for my website, however as a lot of the records have same number of points, they all have same rank, is there a way to avoid this?
currently have
$conn = $db->query("SELECT COUNT( * ) +1 AS 'position' FROM tv WHERE points > ( SELECT points FROM tv WHERE id ={$data['id']} )");
$d = $db->fetch_array($conn);
echo $d['position'];
And DB structure
`id` int(11) NOT NULL,
`name` varchar(150) NOT NULL,
`points` int(11) NOT NULL,
Edited below,
What I'm doing right now is getting records by lets say
SELECT * FROM tv WHERE type = 1
Now I run a while loop, and I need to make myself a function that will get the rank, but it would make sure that the ranks aren't duplicate
How would I go about making a ranking system that doesn't have same ranking for two records? lets say if the points count is the same, it would order them by ID and get their position? or something like that? Thank you!
If you are using MS SQL Server 2008R2, you can use the RANK function.
http://msdn.microsoft.com/en-us/library/ms176102.aspx
If you are using MySQL, you can look at one of the below options:
http://thinkdiff.net/mysql/how-to-get-rank-using-mysql-query/
http://www.fromdual.ch/ranking-mysql-results
select #rnk:=#rnk+1 as rnk,id,name,points
from table,(select #rnk:=0) as r order by points desc,id
You want to use ORDER BY. Applying on multiple columns is as simple as comma delimiting them: ORDER BY points, id DESC will sort by points and if the points are the same, it will sort by id.
Here's your SELECT query:
SELECT * FROM tv WHERE points > ( SELECT points FROM tv WHERE id ={$data['id']} ) ORDER BY points, id DESC
Documentation to support this: http://dev.mysql.com/doc/refman/5.0/en/sorting-rows.html
Many Database vendors have added special functions to their products to do this, but you can also do it with straight SQL:
Select *, 1 +
(Select Count(*) From myTable
Where ColName < t.ColName) Rank
From MyTable t
or to avoid giving records with the same value of colName the same rank, (This requires a key)
Select *, 1 +
(Select Count(Distinct KeyCol)
From myTable
Where ColName < t.ColName or
(ColName = t.ColName And KeyCol < t.KeyCol)) Rank
From MyTable t

Calculating a row position in the table

Let's say I have a table like this (this is just a simplified example, the real table I'm talking about is much more complex):
CREATE TABLE media (
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
voted INT NOT NULL DEFAULT 0,
rating FLOAT NOT NULL DEFAULT 0
) ENGINE = INNODB;
The voted column represents a number of votes the item has received and the rating column represents the total rating of the item.
Now, what I want to do is select a single item from the table based on id, something like:
SELECT m.* FROM media AS m WHERE id = 5;
But, in addition, I want to calculate the position of this row based on the rating column and fetch that as an additional column, let's say called a site_rank (so the bigger the rating of the row is the higher its site_rank will be, I hope I explained it well). My guess is this can be achieved with a subselect query but I'm not sure how to do it.
Any help?
SELECT count(*) FROM media WHERE rating > (SELECT rating FROM media WHERE id = 5);
This will output high rank for most voted media.
If you want low rank for the most voted (like, the most voted gets the rank of 1), just reverse the sign in the subquery.
SELECT mo.*,
(
SELECT COUNT(*)
FROM media mi
WHERE (mi.rating, mi.id) <= (mo.rating, mo.id)
) AS rank
FROM media mo
WHERE mo.id = 5
SELECT
m1.*,
(SELECT COUNT(*) FROM media AS m2 WHERE m2.rating > m1.rating) AS site_rank
FROM
media AS m1
WHERE
id = 5;
Note that this does not define a complete ordering because there might be items with equal rating and they will report the same site rank.
Does MySQL support the standard SQL rank() function? It does exactly what you want.
select
*,
rank() over (
order by rating desc
) as site_rank
from media

Categories