MariaDB User procedure loops endlessly - mysql

I have the following stored procedure to calculate running averages. However when called, it runs forever.
delimiter //
CREATE PROCEDURE run_avg(date_start DATE,date_end DATE,pol_id TINYINT,sta_id TINYINT)
NOT DETERMINISTIC
CONTAINS SQL
BEGIN
TRUNCATE average_table;
WHILE date_start <= date_end DO
INSERT INTO average_table(value_avg)
SELECT AVG(a.value) as val
FROM (SELECT value FROM obs_all_unik
WHERE start_time >=date_start
AND start_time < date_start + INTERVAL 8 HOUR
AND polutant_id=pol_id
AND station_id=sta_id) AS a;
SET date_start = date_start + INTERVAL 1 HOUR;
END WHILE;
END;//
delimiter ;
Any ideas?

INDEX(station_id, polution_id, start_date)
would help performance.
It seems wrong to insert just the averages into the table without also inserting these values: station_id, polution_id, start_date.

The endless loop was due to a wrong definition of date_start as DATE. Since I tried to increment by hours it was returning one and the same value. I changed it to TIMESTAMP and now the problem is gone.

Related

mysql trigger to calculate elapsed minutes

I have a table with start_date and end_date both datetime type.
I need a trigger that calculate the elapsed minutes between both dates and update the result on the duration field on the same table when the end_date is updated.
For some reason all I try gives me Syntax error.
I'm using phpMyAdmin sql window to do it.
Please help.
CREATE TRIGGER 'my_trigger'
BEFORE UPDATE ON `table`
FOR EACH ROW
BEGIN
IF NEW.end_date IS NOT NULL THEN
SET NEW.duration = (UNIX_TIMESTAMP(NEW.end_date) - UNIX_TIMESTAMP(OLD.start_date)) / 60
END IF;
END //

mysql trigger function using date add function

I am trying to create a trigger using the date add function in mysql using phpadmin and getting a syntax error; my goal is to automatically add a date in the estimated finish date column ie 'fin_dt' which is 14 days from the date the order is placed. Ie current date plus 14 days. I have come up with the following mysql state but get an error:
DELIMITER $$
CREATE TRIGGER before_insert_orderin BEFORE INSERT ON order_in
BEGIN
SET NEW.fin_dt = SELECT DATE_ADD(CURDATE(), INTERVAL 14 DAY) ;
END $$
Your trigger syntax is wrong. You are missing for each row and also you do not need select to set the value. It should be as
delimiter //
create trigger before_insert_orderin before insert on order_in
for each row
begin
set new.fin_dt = date_add(curdate(),interval 14 day);
end ; //
delimiter ;
Your Trigger syntax near " SET NEW.fin_dt = SELECT DATE_ADD(CURDATE(), INTERVAL 14 DAY)"
SELECT DATE_ADD is Wrong. It should be as
CREATE TRIGGER `before_insert_orderin`
BEFORE INSERT ON `order_in`
FOR EACH ROW
SET NEW.fin_dt=DATE_ADD(NOW(), INTERVAL 14 DAY)

mysql stored procedure doesn't work for the last day of month

I am on a MySQL DB. I have a scheduled event that calls a procedure every night and inserts some data based on the previous day in a table.
All works fine except for the last day of a month. The procedure delivers an empty set. I have tried to run the procedure also without scheduling, and I get an empty set as well. So I think there is something fishy in the procedure itself (how I define "datum" aka date f.e.), not in the scheduling. Any ideas fix this or do it right? THANKS!
| data | |
CREATE DEFINER=`developer`#`localhost` PROCEDURE `data`(p_start_date DATE, p_end_date DATE)
BEGIN
DECLARE datum DATE;
SET datum = p_start_date;
WHILE datum < p_end_date DO
INSERT INTO DB_name.table_name select ... where ... and a.entrydate>=datum - 1 and a.entrydate<datum group by date(a.entrydate);
SET datum = DATE_ADD(datum, INTERVAL 1 DAY);
END WHILE;
END | utf8 | utf8_general_ci | utf8_general_ci |
a.entrydate>=datum - 1? Since datum is a date, you're going to end up with a float for that result, e.g. select now()-1 comes back as 20140303090955.0000.
perhaps you want
... where ... and a.entrydate >= (datum - INTERVAL 1 DAY)
instead.

MySql stored procedure to update the database record

I hasn't been writing any MySql stored procedures before, so I don't know them at all. I have one database table which has some records in it. The main column is dateTime - when this record was saved in the database.
I have wrote the MySql stored procedure to select every record from the specified date:
CREATE PROCEDURE getMessages(IN dateFrom DATETIME)
SELECT * FROM EsbMessage WHERE dateTime <= dateFrom;
And this is the call:
CALL getMessages('2012-10-04 13:11:09');
This works correctly, it returns me the records from the specified date.
What I need to do is:
If the record is over one week old, I need to update the other
column.
If the record is over one year old, I need to delete that record.
I can easily do this programmatically, but in this case I have to do this using stored procedure.
So I'am thinking of something like this:
CREATE PROCEDURE updateMessages(IN dateFrom DATETIME)
BEGIN
SELECT * FROM EsbMessage WHERE dateTime <= dateFrom;
#for each message
#if the message is over one week old but not over one year old:
UPDATE EsbMessage SET body = '';
#if message is over one year old:
DELETE FROM EsbMessage WHERE dateTime = #message.dateTime
END
But I don't know how to use for loop in stored procedure, and how to write if statements depending on my requirements and the other thing I don't now how to count the dates in MySql. For e.g. If I have the current date then I need to subtract the 365 days from the current date.
Could somebody help me with this issue?
You wouldn't need a loop, just have your conditions in the WHERE clause:
#if the message is over one week old but not over one year old:
UPDATE EsbMessage SET body = ''
WHERE dateTime >= DATE_SUB(NOW(),INTERVAL 1 WEEK) AND dateTime <= DATE_SUB(NOW(),INTERVAL 1 YEAR);
#if message is over one year old:
DELETE FROM EsbMessage WHERE dateTime >= DATE_SUB(NOW(),INTERVAL 1 YEAR);
How to loop and to use if clauses is described here: http://www.mysqltutorial.org/stored-procedures-loop.aspx
I would do it without loops:
CREATE PROCEDURE updateMessages(IN dateFrom DATETIME)
BEGIN
UPDATE EsbMessage SET body = '' where dateTime <= dateFrom -(86400*7); //86400 = 1 day
#if message is over one year old:
DELETE FROM EsbMessage where dateTime <= dateFrom -(86400*365);
END

How to calculate date using interval from table

I have a table with a start_date, end_date and an interval. I would like to update end_date with the value of start_date and the interval.
create table date_test (
start_date date,
end_date date,
date_interval varchar(45)
);
The values I am using for date_interval are like - INTERVAL 1 WEEK, + INTERVAL 1 MONTH.
I would like to do something like:
UPDATE date_test SET end_date = date( concat( start_date, " ", date_interval));
but I get this warning:
1292 Truncated incorrect date value: '2012-01-01 - INTERVAL 1 week'
How can I force this date to get evaluated before updating?
Jonathan Leffler said :
Nearly; there's a crucial difference between the manual page and the question, though. The manual discusses DATE_ADD(date_value, INTERVAL '1' DAY) etc, whereas the question would be having a 'string' value as the second parameter. I fear the question would need a function to convert the string into an INTERVAL type. There doesn't appear to be a 'TO_INTERVAL' function in MySQL.
Here is a function that will take the date as first parameter and the string interval as second parameter.
Simply add the following stored procedure to your database :
CREATE PROCEDURE my_date_add(d DATE, i VARCHAR(50))
BEGIN
DECLARE sign CHAR(1);
DECLARE x INT;
SET sign = SUBSTRING_INDEX(i, ' ', 1);
SET x = SUBSTRING_INDEX(SUBSTRING_INDEX(i, ' ', -2), ' ', 1);
IF sign = '-' THEN
SET x = -x;
END IF;
CASE SUBSTRING_INDEX(i, ' ', -1)
WHEN 'DAY' THEN SELECT DATE_ADD(d, INTERVAL x DAY);
WHEN 'WEEK' THEN SELECT DATE_ADD(d, INTERVAL x WEEK);
WHEN 'MONTH' THEN SELECT DATE_ADD(d, INTERVAL x MONTH);
END CASE;
END
Then you should be able to update your table like this :
UPDATE date_test SET end_date = my_date_add(start_date, date_interval);
What you want to do is :
UPDATE date_test SET end_date = DATE_ADD(start_date, date_interval);
But I'm not sure that using date_interval as the second parameter will work, tell us if it does.
You will find a lot of useful examples in the MySQL documentation, see DATE_ADD() function description.
MySQL does not support values evaluating. So, you cannot use an UPDATE statement directly.
In this case I'd suggest you these ways:
Write a SELECT...INTO OUTFILE statement that would generate a list of UPDATE statemants and output all this statements into the file, then just run this sript.
Or write a stored procedure that would open a cursor on date_test table, in a loop generate and execute UPDATE statements for each record, one by one, using prepared statements.
Ask, if you have a questions about the solutions.