I have a table named service_tracker. The table contains 6 fields but the most relevant to my question below is cycle_start and last_used. Currently I am able to determine the following things about a service: the times it has been used (usage_count) by user within 1 month (last_used,cycle_start). First query adds 1 to the usage_count as long as it is not older then 1 month. Second query clears and sets the usage_count = 1 if older than 1 month. Queries work great, however, would it possible to perform this on the basis of the twelve months of the year? Clear and set to 1 the usage_count once April, May, June etc. is over?
Queries:
UPDATE service_tracker
SET usage_count = usage_count + 1,
last_used = CURDATE()
WHERE service_tracker = 'cloudstorage' AND `user` = 'test2' AND last_used >= date_sub(CURDATE(), INTERVAL 1 month);
UPDATE service_tracker
SET usage_count = 1,
last_used = '0000-00-00',
cycle_start = CURDATE()
WHERE service_tracker = 'cloudstorage' AND `user` = 'test2' AND cycle_start < date_sub(CURDATE(), interval 1 month);
Table Schema
CREATE TABLE IF NOT EXISTS `service_tracker` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`service` varchar(50) NOT NULL,
`cycle_start` date NOT NULL,
`user` varchar(200) NOT NULL,
`usage_count` int(6) NOT NULL,
`last_used` date NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `service_tracker` (`id`, `service`, `cycle_start`, `user`, `usage_count`, `last_used`) VALUES
(1, 'webserver', '2015-04-24', 'test1', 13, '2015-04-24'),
(2, 'cloudstorage', '2015-04-16', 'test2', 390, '2015-04-30'),
(3, 'web-traffic-tracker', '2015-04-16', 'test3', 1916, '2015-04-30'),
(4, 'remote-it-help', '2015-04-16', 'test4', 91, '2015-04-16');
You can use the mysql scheduler to run queries at specific (and repeating) times.
DELIMITER $$
CREATE EVENT reset_usage_count
ON SCHEDULE EVERY '1' MONTH
STARTS '2015-05-01 00:00:00'
DO
BEGIN
-- your query to reset the usage_count
END$$
DELIMITER ;
This one would start the query at midnight, on the first of every month. You will need to make sure the global variable event_scheduler is set to on. You can check that it is running by executing show proceslist, and looking for User: event_scheduler
Related
I have following procedures which help me to update the dates in my table on a daily basis, keeping them relevant for demo purposes. The difference between those two procedures is only that they are being executed for 2 different clients with property_id being 2 and 3 respectively.
UPDATE `opera_pms_detail` SET `arrival` = SUBDATE(curdate(), 2), `departure` = SUBDATE(curdate(), 1), `read_on` = NULL WHERE `property_id` = 2 AND `import_type` = '1'
UPDATE `opera_pms_detail` SET `arrival` = SUBDATE(curdate(), 2), `departure` = SUBDATE(curdate(), 1), `read_on` = NULL WHERE `property_id` = 3 AND `import_type` = '1'
Now, for efficiency's sake, is there a better way of doing this? Instead of having to call the procedure twice, can I just update the columns for both clients in one call?
Thank you
Try implementing your procedure like this
PROCEDURE ýour_procedure_name(IN p_property_id INT)
BEGIN
UPDATE `opera_pms_detail`
SET `arrival` = SUBDATE(curdate(), 2),
`departure` = SUBDATE(curdate(), 1),
`read_on` = NULL
WHERE `property_id` = p_property_id
AND `import_type` = '1';
END
And you will call your procedure as:
CALL `your_procedure_name`(property_id)
I am trying to create a procedure in MySQL that insert weeks (for current year) to my week table. But there is a problem because after first row is added for the next one I get an error: number column cannot be null. I am new to MySQL so I will appreciate any help.
CREATE PROCEDURE generateWeeks()
BEGIN
SET #currentYear = YEAR(CURDATE());
SET #nextYear = #currentYear + 1;
SET #startOfCurrentWeek = CURDATE();
WHILE(#currentYear < #nextYear) DO
SET #endOfCurrentWeek = DATE_ADD(#startOfCurrentWeek , INTERVAL 7 DAY);
SET #weekNumber = WEEK(#startOfCurrentWeek, 3) -
WEEK(#startOfCurrentWeek - INTERVAL DAY(#startOfCurrentWeek)-1 DAY, 3) + 1;
INSERT INTO `week` (`number`, `start_date`, `end_date`)
VALUES (#weekNumber, #startOfCurrentWeek, #endOfCurrentWeek);
SET #startOfCurrentWeek = #endOfCurrentWeek + 1;
SET #currentYear = YEAR(#endOfCurrentWeek);
END WHILE;
END //
DELIMITER ;
EDITED:
Table Creation:
CREATE TABLE `week` (
`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`number` INT(11) NOT NULL,
`start_date` DATE NOT NULL,
`end_date` DATE NOT NULL
)
Why for first while iteration everything is ok (rows is added), but in the next one I get null value in #weekNumber variable ?
The line:
SET #startOfCurrentWeek = #endOfCurrentWeek + 1;
will convert the variable into a integer. Use date_add instead.
Also, instead of using user-defined variables (#endOfCurrentWeek) you better use local variabled (declare v_endOfCurrentWeek date).
I'm trying to create a table with all the row rappresenting half an hour within 08:00:00 and 20:00:00.
My table:
CREATE TABLE cal (
id INTEGER PRIMARY KEY,
year INTEGER NOT NULL,
month INTEGER NOT NULL,
day INTEGER NOT NULL,
half INTEGER NOT NULL,
hour INTEGER NOT NULL,
checked TINYINT(1) DEFAULT 0, -- Check if is reserved
) Engine = MyISAM;
and my procedure:
CREATE PROCEDURE fill_date_dimension(IN giorno DATE)
BEGIN
DECLARE currentdate DATE;
DECLARE stoppete DATE;
SET currentdate = '08:00:00';
SET stoppete = '20:00:00';
WHILE currentdate < stoppete DO
INSERT INTO cal VALUES (
concat(DATE_FORMAT(currentdate, '%Y'),DATE_FORMAT(currentdate, '%m'),DATE_FORMAT(currentdate, '%d'),DATE_FORMAT(currentdate, '%H'),DATE_FORMAT(currentdate, '%i')),
DATE_FORMAT(giorno, '%Y'),
DATE_FORMAT(giorno, '%m'),
DATE_FORMAT(giorno, '%d'),
DATE_FORMAT(currentdate, '%i'),
DATE_FORMAT(currentdate, '%H'),
0);
SET currentdate = DATE_ADD(currentdate,INTERVAL 30 MINUTE);
END WHILE;
END
But when I try to call fill_date_dimension('2017-05-30') it never populate the table.
I think the problem is the while loop and mysql can't loop within hours but only day.
I think you have multiple problems:
you missed a comma (you already addressed that after the update
with the lines SET currentdate = '08:00:00'; and SET stoppete = '20:00:00'; you replace the date you enter with only the time.
the amount of fields you're trying to insert don't correspond
This insert query:
INSERT INTO cal VALUES (
concat(DATE_FORMAT(currentdate, '%Y'),DATE_FORMAT(currentdate, '%m'),DATE_FORMAT(currentdate, '%d'),DATE_FORMAT(currentdate, '%H'),DATE_FORMAT(currentdate, '%i')),
DATE_FORMAT(giorno, '%Y'),
DATE_FORMAT(giorno, '%m'),
DATE_FORMAT(giorno, '%d'),
DATE_FORMAT(currentdate, '%i'),
DATE_FORMAT(currentdate, '%H'),
0);
will insert 7 fields, usually skipping the id field. The concat part will tried to be inserted into the year field, not the id field.
Try an explicit query:
INSERT INTO cal (id,year,month,day,half,hour,checked) VALUES (
concat(DATE_FORMAT(currentdate, '%Y'),DATE_FORMAT(currentdate, '%m'),DATE_FORMAT(currentdate, '%d'),DATE_FORMAT(currentdate, '%H'),DATE_FORMAT(currentdate, '%i')),
DATE_FORMAT(giorno, '%Y'),
DATE_FORMAT(giorno, '%m'),
DATE_FORMAT(giorno, '%d'),
DATE_FORMAT(currentdate, '%i'),
DATE_FORMAT(currentdate, '%H'),
0);
Couple of things to check:
'08:00:00' is not valid date value (use datetime and combine the giorno with date)
id-column is defined as integer and your values are most likely out of range
I'm trying to implement a SQL query to "UPDATE if exists else INSERT"
My table(Allowance) is as below:
EmployeeID int(8) PK
Year year(4) PK
Month int(2) PK
OverTime decimal(10,2)
Medical decimal(10,2)
Lunch decimal(10,2)
Bonus decimal(10,2)
Allowance decimal(10,2)
Below is the SQL query I tried:
IF EXISTS (SELECT * FROM Allowance WHERE EmployeeID =10000001 and Year = 2014 and Month = 4)
UPDATE Allowance
SET OverTime = 10.00, Medical = 10.00, Lunch = 10.45, Bonus =10.10, Allowance = 40.55
WHERE EmployeeID =10000001 and Year = 2014 and Month = 4
ELSE
INSERT into Allowance values (10000001,2014,4,10.00,10.00,10.45,10.10,40.55)
I keep getting this error message:
"#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF EXISTS (SELECT * FROM Allowance WHERE EmployeeID =10000001 and Year = 2014 an' at line 1 "
Can somebody please help??
The below query will fulfill your requirement.
INSERT INTO `ALLOWANCE` (`EmployeeID`, `Year`, `Month`, `OverTime`,`Medical`,
`Lunch`, `Bonus`, `Allowance`) values (10000001, 2014, 4, 10.00, 10.00,
10.45, 10.10, 40.55) ON DUPLICATE KEY UPDATE `EmployeeID` = 10000001
Further to Gunaseelan's answer (answering questions I had myself, that I needed to look up):
INSERT INTO `ALLOWANCE` (`EmployeeID`, `Year`, `Month`, `OverTime`,`Medical`,
`Lunch`, `Bonus`, `Allowance`) values (10000001, 2014, 4, 10.00, 10.00,
10.45, 10.10, 40.55) ON DUPLICATE KEY UPDATE `OverTime`=10.00, `Medical`=10.00, `Lunch`=10.45, `Bonus`=10.10, `Allowance`=40.55;
Don't forget the trailing semicolon (like I did);
WHERE is not required - it knows which record is the duplicate
Also no need to mention the tablename again - that was provided in first half
Here is a page that explains the syntax in more detail:
https://chartio.com/resources/tutorials/how-to-insert-if-row-does-not-exist-upsert-in-mysql/#using-insert--on-duplicate-key-update
With this procedure you can check if exist or not and then update/insert as you want
DELIMITER $$;
CREATE PROCEDURE example()
BEGIN
DECLARE vexist int;
SELECT count(*) into vexist FROM Allowance --count because i will
WHERE EmployeeID =10000001 and Year = 2014 and Month = 4; --this will check if exist or not
IF (vexist >= 1) then --if exist then update
UPDATE Allowance
SET OverTime = 10.00, Medical = 10.00, Lunch = 10.45, Bonus =10.10, Allowance = 40.55
WHERE EmployeeID =10000001 and Year = 2014 and Month = 4;
ELSE
INSERT into Allowance values (10000001,2014,4,10.00,10.00,10.45,10.10,40.55);
END IF;
END $$
DELIMITER ;
You have to call the procedure now:
call example();
Note: This will solve you solution as for now, but it's not the best idea since procedures are intended to get used in the future aswell, so i'll give you an improved version where in the future you will be able to update/insert by just invoking the procedure and wrinting your inserts values.
DELIMITER $$;
CREATE PROCEDURE example(
IN
vempid int(8),
vyear year(4),
vmonth int(2),
vovertime float(10,2),
vmedical float(10,2),
vlunch float(10,2),
vbonus float(10,2),
vallowance float(10,2))
BEGIN
DECLARE vexist int;
SELECT count(*) into vexist FROM Allowance --count because i will
WHERE EmployeeID =vemp and Year = vyear and Month = vmonth; --this will check if exist or not
IF (vexist >= 1) then --if exist then update
UPDATE Allowance
SET OverTime = vovertime, Medical = vmedical, Lunch = vlunch, Bonus = vbonus, Allowance = vallowabce
WHERE EmployeeID =10000001 and Year = vyear and Month = vmonth;
ELSE
INSERT INTO `ALLOWANCE` (`EmployeeID`, `Year`, `Month`, `OverTime`,`Medical`,`Lunch`, `Bonus`, `Allowance`) values (vempid,vyear,vmonth,vovertime,vmedical,vlunch,vbonus,vallowance);
END IF;
END $$
DELIMITER ;
And invoking (with the correct parameters order):
call example2(10000001,2014,4,10.00,10.00,10.45,10.10,40.5);
No need to write custom SQL for this. MySQL already has INSERT ... ON DUPLICATE KEY UPDATE which does exactly same thing.
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUE index or PRIMARY KEY, an UPDATE of the old row is performed.
Please read URL for more details.
SELECT IF (EXISTS()) instead of IF EXISTS()
Usage of MySQL's "IF EXISTS"
I try to use mysql replace with following table.
CREATE TABLE price (
id BIGINT UNSIGNED AUTO_INCREMENT,
ski_chalet_id BIGINT UNSIGNED NOT NULL,
month DATE NOT NULL,
d_1 DOUBLE(18, 2),
d_2 DOUBLE(18, 2),
d_3 DOUBLE(18, 2),
d_4 DOUBLE(18, 2),
d_5 DOUBLE(18, 2),
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
UNIQUE INDEX fk_ski_chalet_price_ski_chalet_idx (ski_chalet_id, month),
INDEX ski_chalet_id_idx (ski_chalet_id),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8 ENGINE = InnoDB;
I want add a row if row is not exist and update if row is exist. So i used mysql REPLACE to do that.
REPLACE INTO `price` SET `ski_chalet_id` = 43 and `month` = '2013-04-01' and `d_1` = 23
This query is successful. but add all value as 00 and 0000-00-00 or null.
But insert query is working.
INSERT INTO `price` (`ski_chalet_id`,`month`,`d_1`) VALUES ('34', '2013-04-01', '46');
I cant find whats the issue. Please help me.
You have to use "," instead on "and" in replace query ........
REPLACE INTO price SET ski_chalet_id = 43 , month = '2013-04-01' , d_1 = 23
NOTE : REPLACE function will work want you want you don't have to look for other functions.
Don't use SET with REPLACE. The syntax for REPLACE is the same as for INSERT:
REPLACE INTO `price` (`ski_chalet_id`,`month`,`d_1`) VALUES ('43', '2013-04-01', '23');
To specify multiple columns with SET in REPLACE (and UPDATE / INSERT), you must separate them with commas. Your query amounts to:
SET `ski_chalet_id` = (some boolean expression)
Rewrite as
SET `ski_chalet_id` = 43, `month` = '2013-04-01', `d_1` = 23