I have a table with time column.
CREATE TABLE `mbusGuestCodeExpires` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hashOfUser` int(11) NOT NULL,
`expiresTime` time DEFAULT NULL,
`active` int(1) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `hashOfUser` (`hashOfUser`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 PACK_KEYS=0;
and input which has value of this field and user can change it, where $expireTime is time from table and $timeDiffHour and $timeDiffMinute are time left to time from table.
echo "<div class='expires'>Expires:<input type='text' class='expiresTime' value='{$expireTime}'/></div><div class='left'>";
if (($timeDiffHour>=0) && ($timeDiffMinute>0))
{
echo"Left:".$timeDiffHour."h. ".$timeDiffMinute." min.";
}
echo"</div>";
I need now change the field active to 0 when it is $expireTime time. What is the best way to do it except running cron script every minute that check all the column and checks its value if it's less current time?
How about:
select ... where expiresTime < curtime()
Doc ref: http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_curtime
Related
I have 2 tables on my DB: user_notification and user_notification_read. It's a user notification system, the notifications are on user_notification and when a user reads a notification, it stores on user_notification_read with the notification id and the user id.
CREATE TABLE `user_notification` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`related_user_id` int(11) NOT NULL,
`text` text NOT NULL,
`link` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `user_notification_read` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`notification_id` int(11) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `notification_id` (`notification_id`),
CONSTRAINT `user_notification_read_ibfk_1` FOREIGN KEY (`notification_id`) REFERENCES `user_notification` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I want to make a SELECT to get the number of unread notifications for a certain user (by the user id).
I thought about using a
JOIN/WHERE (notification.id = user_notification_read.notification_id and user_notification.user_id = X)to get the rows from user_notification_read with a CASE to check if the row exists. If it doesn't exists, +1 on unread notifications.
I don't know if that's the appropriate logic to achieve it and don't know the syntax as well. I tried some google, but the examples are more complex than my case, which I believe it's simple.
How can I do that?
Fiddle: http://sqlfiddle.com/#!9/84a5ed/5/0
On the fiddle example, the count for unread notifications would be 2 for the user 1.
You should use a left join.
SELECT sum(r.notification_id is null)
FROM user_notification n
LEFT JOIN user_notification_read r ON r.notification_id = n.id
WHERE n.user_id = 1
r.notification_id is null means a notification wasn't read.
Here is my function which i am using to un-follow users.It first DELETE the relationship between users and all the notifications that are related to this relationship.Then it INSERT a new notification for user which we are going to un-follow and then UPDATE his followers count (as one follower has left).I am using multi_query and this query seems to be bit slower on large database and i want to know whether it's a good practice or not or is there is any more complex form of query to get the job done.
PHP Function
// 'By' is the array that hold logged user and 'followed' is the user id which we are going to unfollow
function unFollowUser($followed,$by) {
$following = $this->getUserByID($followed);// Return fetch_assoc of user row
if(!empty($following['idu'])) { // if user exists
// return user followers as number of rows
$followers = $this->db->real_escape_string($this->numberFollowers($following['idu'])) - 1;
$followed_esc = $this->db->real_escape_string($following['idu']);
$by_user_esc = $this->db->real_escape_string($by['idu']);
// delete relationship
$query = "DELETE FROM `relationships` WHERE `relationships`.`user2` = '$followed_esc' AND `relationships`.`user1` = '$by_user_esc' ;" ;
// delete notification (user started following you )
$query.= "DELETE FROM `notifications` WHERE `notifications`.`not_from` = '$by_user_esc' AND `notifications`.`not_to` = '$followed_esc' ;" ;
// Insert a new notification( user has unfollowed you)
$query.= "INSERT INTO `notifications`(`id`, `not_from`, `not_to`, `not_content_id`,`not_content`,`not_type`,`not_read`, `not_time`) VALUES (NULL, '$by_user_esc', '$followed_esc', '0','0','5','0', CURRENT_TIMESTAMP) ;" ;
// update user followers (-1)
$query .= "UPDATE `users` SET `followers` = '$followers' WHERE `users`.`idu` = '$followed_esc' ;" ;
if($this->db->multi_query($query) === TRUE) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
Table structures
--
-- Table structure for table `notifications`
--
CREATE TABLE IF NOT EXISTS `notifications` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`not_from` int(11) NOT NULL,
`not_to` int(11) NOT NULL,
`not_content_id` int(11) NOT NULL,
`not_content` int(11) NOT NULL,
`not_type` int(11) NOT NULL,
`not_read` int(11) NOT NULL,
`not_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Table structure for table `relationships`
--
CREATE TABLE IF NOT EXISTS `relationships` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user1` int(11) NOT NULL,
`user2` int(11) NOT NULL,
`status` int(11) NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Table structure for table `users`
--
CREATE TABLE IF NOT EXISTS `users` (
`idu` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL,
`password` varchar(256) NOT NULL,
`email` varchar(256) NOT NULL,
`first_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`last_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`verified` int(11) NOT NULL,
`posts` text CHARACTER SET utf32 NOT NULL,
`photos` text CHARACTER SET utf32 NOT NULL,
`followers` text CHARACTER SET utf32 NOT NULL,
UNIQUE KEY `id` (`idu`),
UNIQUE KEY `idu` (`idu`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
In my testing, multi_query has been the fastest way to execute multiple different queries. Why do you feel it's running slow? Compared to what?
Anyway, improvements could come from adding indexes to some of the columns you search frequently:
relationships.users2
relationships.users1
notifications.not_from
notifications.not_to
users.idu
Adding indexes makes searching faster, but it has at least two downsides:
Makes the DB a lot more resource hungry, which could affect your server performance
Makes writing operations take longer
I don't see any problem with your current queries. Really consider whether the slow performance you're seeing comes from the DB queries themselves, or from the rest of your PHP process. Try measuring the script time with the queries, then skipping the queries and taking another measurement (you could hardcode query results). It will give you an idea of whether the slowness is attributable to something else.
Either way, benchmark.
Try creating index on user where deletes are running , this may speed up query
CREATE TABLE IF NOT EXISTS `comenzi` (
`idcomanda` int(11) NOT NULL AUTO_INCREMENT,
`iduser` int(11) DEFAULT NULL,
`idprodus` int(11) DEFAULT NULL,
`numepiesa` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`pretunit` int(11) DEFAULT NULL,
`cantitate` int(11) DEFAULT NULL,
`pretftva` int(11) DEFAULT NULL,
`valtva` int(11) DEFAULT NULL,
`total` int(11) DEFAULT NULL,
`nrfactura` int(11) unsigned zerofill DEFAULT NULL,
`achitat` tinyint(4) DEFAULT NULL,
`dataachitat` date DEFAULT NULL,
PRIMARY KEY (`idcomanda`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Hey Guys,I have the table structure mentioned above and I never did triggers in MySQL, could you help me out with this one please.
I need to update the "dataachitat"column with the currentdate everytime a row has the "achitat" value set to 1
Ex. Let's say that the first item is affected by an update script and the achitat value is set to 1, i need the "dataachitat" column of that row to be automatically set to currentdate.
Please help me out
Cheers !
A BEFORE UPDATE trigger to perform the specified action would look something like this:
DELIMITER $$
CREATE TRIGGER trg_comenzi_bu
BEFORE UPDATE ON comenzi
FOR EACH ROW
BEGIN
IF NEW.achitat = 1 THEN
SET NEW.dataachitat = DATE(NOW());
END IF;
END$$
DELIMITER ;
(This is desk checked only; there could be issues with the order of the keywords; the BEFORE UPDATE might come after ON comenzi, et al.)
NOTE: The BEFORE UPDATE trigger will only be "fired" when an UPDATE statement affects a row in the table, it won't be fired when a row is inserted to the table. You'd need an equivalent BEFORE INSERT trigger to do the same thing on an INSERT.
NOTE: The IF statement in the trigger body checks if the value of the achitat column is 1; it doesn't check if the previous (OLD) value was something other than 1. That is, the IF will evaluate to TRUE whether the achitat was changed to a 1, or if it was already a 1.
If you only want the SET action to be performed if the achitat column is changed to 1 from some other value, you could do something like this:
IF (NEW.achitat = 1 AND (OLD.achitat <> 1 OR OLD.achitat IS NULL)) THEN
So I have a loop to be nested inside another loop based on two queries. I have the first loop working fine-
$sql_categories = mysql_query("SELECT * FROM $categories_table");
$results = mysql_query("SELECT * FROM $events_table");
while ($num_rows = mysql_fetch_assoc($sql_categories)) {
extract($num_rows);
echo "<h2>$category_name</h2>";
// Begin second loop to output events
while/for(not sure) {
}
}
I want to output into the second loop all the $vars for the corresponding $category_id. In the second query, the matching value is $event_category_id.
I don't know if that makes sense, but what I'm trying to get is basically--
<h2>Category One</h2>
Event Name
Event Name
Event Name
<h2>Category Two</h2>
Event Name
Event Name
Event Name
etc. where the "Event Name" corresponds to the "Category Name"
The two tables I'm working with look like this-
CREATE TABLE `wp_wild_dbem_categories` (
`category_id` int(11) NOT NULL auto_increment,
`category_name` tinytext NOT NULL,
PRIMARY KEY (`category_id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
CREATE TABLE `wp_wild_dbem_events` (
`event_id` mediumint(9) NOT NULL auto_increment,
`event_author` mediumint(9) default NULL,
`event_name` tinytext NOT NULL,
`event_start_time` time NOT NULL default '00:00:00',
`event_end_time` time NOT NULL default '00:00:00',
`event_start_date` date NOT NULL default '0000-00-00',
`event_end_date` date default NULL,
`event_notes` text,
`event_rsvp` tinyint(1) NOT NULL default '0',
`event_seats` tinyint(4) default NULL,
`event_contactperson_id` mediumint(9) default NULL,
`location_id` mediumint(9) NOT NULL default '0',
`recurrence_id` mediumint(9) default NULL,
`event_category_id` int(11) default NULL,
UNIQUE KEY `event_id` (`event_id`)
) ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=latin1
Thanks for your help!
You need to do the second query inside the while loop for it to have any meaningful effect:
$sql_categories = mysql_query("SELECT * FROM $categories_table");
while($category = mysql_fetch_assoc($sql_categories)) {
extract($category);
$events = mysql_query("SELECT * FROM $events_table WHERE event_category_id = '".mysql_real_escape_string($category_id)."'");
echo "<h2>$category_name</h2>";
while($event = mysql_fetch_assoc($events) {
extract($category);
echo "<p>$event_name</p>";
}
}
This should get you where you want, but note that this is not the optimal way to do things. You should first get all of the events, build an array of them indexed by event_category_id and loop that array inside your while loop. This is because now you are doing one extra query per each category whereas only two queries in total should suffice.
But perhaps this would get you started on that then.
I have a simple table as below.
CREATE TABLE `stats` (
`id` int(11) NOT NULL auto_increment,
`zones` varchar(100) default NULL,
`date` date default NULL,
`hits` int(100) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
So just storing simple hits counter per zone per day.
But I just want to increment the hits value for the same day.
I have tried the MYSQL DUPLICATE KEY UPDATE but this wont work as I may have many zones on different dates so I cant make them unique or dates.
So the only way I can think is first to do a query to see if a date exists then do a simple if() for insert/update
Is their a better way of doing such a task as there maybe be many 1000's hits per day.
Hope this makes sense :-).
And thanks if you can advise.
Declare the tuple (zone, date) as unique in your CREATE statement. This will make INSERT ... ON DUPLICATE UPDATE work as expected:
CREATE TABLE `stats` (
`id` int(11) NOT NULL auto_increment,
`zone` varchar(100) default NULL,
`date` date default NULL,
`hits` int(100) default NULL,
PRIMARY KEY (`id`),
UNIQUE (`zone`, `date`)
) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
INSERT INTO stats (zone, date, hits) values ('zone1', 'date1', 1) ON DUPLICATE KEY UPDATE hits = hits + 1;
$result = mysql_query("SELECT id FROM stats WHERE zone=$zone AND date=$today LIMIT 1");
if(mysql_num_rows($result)) {
$id = mysql_result($result,0);
mysql_query("UPDATE stats SET hits=hits+1 WHERE id=$id");
} else {
mysql_query("INSERT INTO stats (zone, date, hits) VALUES ($zone, $today, 1)");
}
Something like that, if I've interpreted you correctly... that's completely untested. You can figure out what the variables are.