MySQL Trigger doesn't update table - php

I created the following trigger in a MySQL database. It's for a star rating system. Whenever a row is added to the ratings table, it's supposed to add this to the ratings_totals table.
DELIMITER$$
create trigger update_vote_after_insert_trig before insert
on ratings
for each row begin
if bookID = new.bookID then
update ratings_totals set
total_votes = total_votes + 1,
total_rating = total_rating + new.rating,
overall_rating = total_rating / total_votes;
where
bookID = new.bookID;
ELSE
insert into ratings_totals set bookID = new.bookID, total_votes = total_votes, total_rating = total_rating, overall_rating = overall_rating;
END IF;
END$$
DELIMITER ;
My problem is that the ratings_totals table is incorrectly updated. It contains four rows: bookID, total_votes, total_rating and overall_rating. Only the bookID table is updated; the rest remain at 0.
My goal is to INSERT the row the first time, and update it after that. Am I doing this right?

If you want to insert at the first time and just update after the first time you can try to use "IF" statement.
if(this is the first time)
///your code
else
// your code
you can use "select" to find out if you inserted this row before and this will be your "IF"

shouldn't the "new" be "old"? Like:
DELIMITER $$
create trigger update_vote_after_insert after insert
on ratings
for each row begin
update ratings_totals set
total_votes = total_votes + 1,
total_rating = total_rating + old.rating,
overall_rating = total_rating / total_votes
where
bookID = old.bookID;
end$$
DELIMITER ;

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 .

ON DUPLICATE KEY: Ambiguous

Following db structure:
Table cms_pages containing pages with id, name, title, etc.
Table cms_pagerows containing rows with a cms_page_id and rank
(Unique index over cms_page_id, rank)
The Pagerows are supposed to contain cols which in turn contain the... content.
I now want to insert a new pagerow into cms_pagerows on an existing page using php.
Ranks are not necessarily consecutive numbers because of the deletion of old pagerows.
For this, I have a function insertRowAt($page_name, $offset) with the following SQL:
INSERT INTO `cms_pagerows` (`cms_page_id`, `rank`)
SELECT `cms_pages`.`id`, `cms_pagerows`.`rank` + 1
FROM `cms_pages`, `cms_pagerows`
WHERE `cms_pages`.`name` = "'.$page_name.'"
AND `cms_pagerows`.`cms_page_id` = `cms_pages`.`id`
ORDER BY `rank` DESC
LIMIT 0, "'.$offset.'"
ON DUPLICATE KEY UPDATE `cms_pagerows`.`rank` = `cms_pagerows`.`rank` + 1
When trying to run it, I get the following error message: "Column 'cms_pagerows.rank' in field list is ambiguous"
The key is to always use table aliases to disambiguate the columns:
INSERT INTO `cms_pagerows`(`cms_page_id`, `rank`)
SELECT p.`id`, pr.`rank` + 1
FROM `cms_pages` p join
`cms_pagerows` pr
on pr.`cms_page_id` = p.`id`
WHERE p.`name` = "'.$page_name.'"
ORDER BY pr.`rank` DESC
LIMIT 0, "'.$offset.'"
ON DUPLICATE KEY UPDATE `rank` = pr.`rank` + 1;
You can also say:
ON DUPLICATE KEY UPDATE `rank` = VALUES(`rank`)
This works because the select is already going to insert the correct rank, so you can just use that value.
try this..
INSERT INTO `cms_pagerows` (`cms_page_id`, `rank`)
SELECT `cms_pages`.`id`, `cms_pagerows`.`rank` + 1 AS rank1
FROM `cms_pages`, `cms_pagerows`
WHERE `cms_pages`.`name` = "'.$page_name.'"
AND `cms_pagerows`.`cms_page_id` = `cms_pages`.`id`
ORDER BY rank1 DESC
LIMIT 0, "'.$offset.'"
ON DUPLICATE KEY UPDATE `rank` = rank1 + 1
two rank fields are conflicting because you are using same name... use AS keyword of mysql..

limit maximum input to the database php mysql?

how can i limit the maximum number of rows in mysql. For example, if the number of grade 4, section 1 students is 30 or over, the user cannot add another student.
first count the rows of the given conditions
$res = mysql_query("SELECT count(*) as cnt FROM `your_table` WHERE grade='4' AND section='1'");
$row = mysql_fetch_assoc($res);
if($row['cnt']<30)
{
// insert student
}
else
{
// not to insert student
}
DELIMITER $$
CREATE TRIGGER trigger1
BEFORE INSERT
ON table1
FOR EACH ROW
BEGIN
SELECT COUNT(*) INTO #cnt FROM table1;
IF #cnt > 30 THEN
/**raise an error**/
END IF;
END
$$
DELIMITER ;

Using php and Mysql to Order by highest number and confirmation

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();

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

Categories