I have a field called pending and been declared as Boolean with default value of 0 as:
`pending` tinyint(1) NOT NULL DEFAULT '0'
I am running an Update query againt the database to change the state of qpending to 1 like below
$sql = "UPDATE `appointments` SET `pending` = '1' WHERE `appointments`.`id` = 124;
now my question is, is there any way to automatically re-state the pending to 0 after 30 minutes by taking a conditional clause like
// After 30 Minutes of update!
if (!confirmed){
$sql = "UPDATE `appointments` SET `pending` = '0' WHERE `appointments`.`id` = 124;
}
Table Schema
CREATE TABLE IF NOT EXISTS `appointments` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`date` varchar(100) CHARACTER SET utf8 NOT NULL,
`available` tinyint(1) NOT NULL DEFAULT '1',
`pending` tinyint(1) NOT NULL DEFAULT '0',
`confirmed` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
You are doing it wrong.
Make your pending field not a boolean but a datetime, with the value of the due time. Then in your select queries just compare that value with the current time. So instead of
SELECT * FROM appointments WHERE pending = 1
just make it
SELECT * FROM appointments WHERE pending < NOW()
this solution is either much simpler and more flexible
Related
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
I am trying to generate invoice id in each invoice, now i am having thousands of invoices, Now while adding from different ip same time i am getting duplicate invoice ids how to prevent it,
invoice id generating by getting the last inserted invoice id and increment 1 to it.
my function as follows parameters
get_new_tbl_id('table_name','invoice_id_column','string to strip (INV in INV0012)','any conditions');
function get_new_tbl_id($tbl_name,$id_field,$string,$options='')
{
$new_id = 0;
$query_count_rows = "SELECT MAX(CONVERT(replace(replace($id_field,',',''),'$string',''), SIGNED INTEGER)) as $id_field FROM $tbl_name WHERE $id_field LIKE '$string%' $options";
$count_rows = mysql_query($query_count_rows);
$num_rows = mysql_num_rows($count_rows);
if($num_rows >0)
{
$last_row = mysql_fetch_assoc($count_rows);
$last_id = $last_row[$id_field];
$last_inserted_id = intval(str_replace($string,'',$last_id));
$new_id = $last_inserted_id+1;
}
else
$new_id = 1;
$format = '%1$03d';
$new_id=sprintf($format,$new_id,'');
return $string.$new_id;
}
My table as follows
CREATE TABLE IF NOT EXISTS `tbl_invoice` (
`invoice_tbl_id` int(11) NOT NULL AUTO_INCREMENT,
`invoice_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`invoice_ip` varchar(25) NOT NULL,
`invoice_status` tinyint(1) NOT NULL DEFAULT '0',
`invoice_added_by` smallint(6) NOT NULL,
`invoice_edited_by` smallint(6) NOT NULL,
`invoice_date` date NOT NULL,
`invoice_id` varchar(15) NOT NULL,
`customer_id` varchar(11) NOT NULL,
`invoice_credit_date` tinyint(4) NOT NULL,
`invoice_credit_status` tinyint(1) NOT NULL DEFAULT '0',
`total_items_count` smallint(6) NOT NULL,
`invoice_total_amount` varchar(20) NOT NULL,
`invoice_grandtotal_amount` double NOT NULL,
`invoice_discount` double NOT NULL DEFAULT '0',
`invoice_total_card_amount` double NOT NULL,
`invoice_total_cash_amount` double NOT NULL,
`invoice_total_profit` varchar(10) NOT NULL,
`cashier_approval` tinyint(1) NOT NULL DEFAULT '0',
`cashier_approval_id` smallint(6) NOT NULL,
`cashier_approval_time` datetime NOT NULL,
`cashier_approval_ip` varchar(20) NOT NULL,
`invoice_delete_note` text NOT NULL,
PRIMARY KEY (`invoice_tbl_id`),
KEY `invoice_id` (`invoice_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Use a myisam table to generate the ids for you with 2 fields. The 1st field contains the prefix (this is $string in your function), the second should be an auto increment field. Add a primary key on these 2 fields, but the prefix field must be the 1st one in the index. If you insert a new row into this table with a prefix, then mysql will increment the auto increment value within that group.
See myisam notes section in mysql documentation on auto increment for details and example.
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
If your base table is mysql, then just alter it to get this behaviour, if not, then create a separate myisam table, do the inserts into that one first, then obtain the ids fo use in your main table.
May there will be some optimized solution, but for now I can give you this solution
use static variable lock if one person is getting id make $lock=true and keep other requests on waiting for 1 second and check again by goto start; until first request is completed; make $lock=false; at the end to release the function.
public static $lock=false;
function get_new_tbl_id($tbl_name,$id_field,$string,$options='')
{
global $lock;
start:
if($lock==true){
sleep(1);
goto start;
}
if($lock==false){
$lock==true;
}
$new_id = 0;
$query_count_rows = "SELECT MAX(CONVERT(replace(replace($id_field,',',''),'$string',''), SIGNED INTEGER)) as $id_field FROM $tbl_name WHERE $id_field LIKE '$string%' $options";
$count_rows = mysql_query($query_count_rows);
$num_rows = mysql_num_rows($count_rows);
if($num_rows >0)
{
$last_row = mysql_fetch_assoc($count_rows);
$last_id = $last_row[$id_field];
$last_inserted_id = intval(str_replace($string,'',$last_id));
$new_id = $last_inserted_id+1;
}
else
$new_id = 1;
$format = '%1$03d';
$new_id=sprintf($format,$new_id,'');
$lock=false;
return $string.$new_id;
}
I have a table with over 10 thousand registers right now, and they start to run so slow.
I have the following code:
COUNT
$SqlCount = "SELECT tabnews.New_Id
FROM tabnew WHERE New_Id <> '' AND New_Status = 1";
$QueryCount = mysql_query($SqlCount, $Conn) or die(mysql_error($Conn));
$NumCount = mysql_num_rows($QueryCount);
$recordCount = $NumCount;
PAGINATION
if (!$id) $p = 1;
else $p = $id;
$pageSize = 16;
$itemIni = ($pageSize*$p)-$pageSize;
$totalPage = ceil($recordCount/$pageSize);
SHOW
$Sql52 = "SELECT New_Id, New_Nome, New_Data, New_Imagem FROM tabnews WHERE New_Status = 1 ORDER BY New_Id DESC LIMIT $itemIni, $pageSize ";
$Query52 = mysql_query($Sql52, $Conn);
while($Rs52 = mysql_fetch_array($Query52)){
// ECHO RESULTS
}
MY DATABASE:
CREATE TABLE IF NOT EXISTS `tabnews` (
`New_Id` int(11) NOT NULL AUTO_INCREMENT,
`Franquia_Id` text NOT NULL,
`New_Slide` int(2) NOT NULL,
`Categoria_Id` int(2) NOT NULL,
`New_Nome` varchar(255) NOT NULL,
`New_Data` date NOT NULL,
`New_Imagem` varchar(75) NOT NULL,
`New_Status` int(11) NOT NULL,
PRIMARY KEY (`New_Id`),
KEY `idx_1` (`New_Status`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10490 ;
Any ideas on how I can make this run faster?
I have a dedicated server running CENTOS.
This:
New_Id <> ''
What does this do? It casts every single one of your INT primary key to string to compare it to a string. Why would you compare it to a string? It cannot be '' by definition, omit that New_Id <> '' from your WHERE clause.
20 seconds is very weird for such a little table.
I have a very similar table with almost 4 million rows and your both SQL statements takes less than 0.002 sec.
CREATE TABLE IF NOT EXISTS `tasks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`status` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'open',
`method` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'GET',
`url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`params` text COLLATE utf8_unicode_ci,
`response` text COLLATE utf8_unicode_ci,
`executed_by` varchar(50) COLLATE utf8_unicode_ci DEFAULT '',
`execute_at` datetime DEFAULT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `status` (`status`),
KEY `modified` (`modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3839270 ;
-
SELECT COUNT(id) FROM tasks WHERE status='done';
---> Query took 0.0008 sec
-
SELECT id, status, method, url FROM tasks WHERE status='done' ORDER BY id DESC LIMIT 200, 100;
---> Query took 0.0011 sec
Observations:
You should use SELECT COUNT(New_Id)...
New_id <> '' doesn't make sense. New_id can't be empty or NULL
Set the length of New_Status to something that match the values you store there
Try turning off logging: SET GLOBAL general_log = 'OFF';
Update your server packages (specially MySQL)
Is it a dedicated server only for the database?
Is the server running other things? (run 'top' and 'uptime' to check it status)
I've got a table created using this query.
CREATE TABLE `tbl_friends` (
`friend_id` int(11) NOT NULL auto_increment,
`friend_status` tinyint(4) NOT NULL default '0',
`friend_id1` int(11) NOT NULL default '0',
`friend_id2` int(11) NOT NULL default '0',
`friend_date` datetime NOT NULL default '0000-00-00 00:00:00',
`friend_confirm` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`friend_id`)
) TYPE=MyISAM AUTO_INCREMENT=10 ;
I want to view the list of my friends, for that I only need to know other user's id - numeric value stored in friend_id1 or friend_id2 rows. My problem is that I don't know if friend_id1 or friend_id2 contains required data.
Please help me create a query to receive the number of another user if my number is $_SESSION['id']
CREATE TABLE `tbl_friends` (
`friend_id` int(11) NOT NULL auto_increment,
`friend_status` tinyint(4) NOT NULL default '0',
`friend_id1` int(11) NOT NULL default '0',
`friend_id2` int(11) NOT NULL default '0',
`friend_date` datetime NOT NULL default '0000-00-00 00:00:00',
`friend_confirm` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`friend_id`)
) TYPE=MyISAM AUTO_INCREMENT=10 ;
Would be like so:
SELECT * FROM tbl_friends WHERE friend_id2 = %d OR friend_id1 = %d AND friend_status != 0 ORDER BY friend_id
More Visual example:
SELECT
*
FROM
tbl_friends
WHERE
friend_id2 = %$1d
OR
friend_id1 = %$1d
AND
friend_status != 0
ORDER BY
friend_id
DESC
Then just run it threw a sprintf function and your ready.
$sql = sprintf($sql,$_SESSION['id']);
I'm not sure what you exactly mean, but I think your looking for something like:
select distinct * from tbl_friends where friend_id1 = $_SESSION["id"] OR friend_id2 = $_SESSION["id"];
If this is not what you mean, please add some additional information.
Something like:
Select distinct(id) from (
select friend_id1 as id from friends where friend_id2 = :my_id
union
select friend_id2 as id from friends where friend_id1 = :my_id
)
There real problem here is keeping the table from getting weird data. You are better off always putting two records into the table for each reciprocal relationship. Then you only need to say:
select * from friends where friend_id1 = :my_id and status = :whatever
If you do it this way, the control data for when friendship happens might need to move to another table
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.