mysql how to assign a date value to a variable - mysql

I'm creating a trigger (before insert) in order to add an updated date, starting from an existing date stored in another table.
Seems that my variable dtStart gets the null value.
This is the code:
BEGIN
DECLARE dtStart DATE;
DECLARE dtRenew DATE;
DECLARE numD INT;
SET dtStart = (SELECT dtStart FROM tblCourses WHERE idCourse = NEW.idCourse);
SET numD = (SELECT setting FROM tblSettings WHERE codSetting = 'D_EXPIRE_C');
SET dtRenew = DATE_ADD(dtStart, INTERVAL numD DAY);
SET NEW.dtExpiration = dtRenew;
END

Related

SSRS show list of weeks

Is there a way I can create a list of weeks (param):w1,W2,... based on another param list (years), so the first list is for the years and the second is for the weeks corresponding to the chosen year.
For example if I choose 2017 from my first list my second list (weeks) should be updated with labels W1,W2,... & the values are the corresponding dates in the given year.
Try this ...
declare #year as int
declare #startdate as datetime
declare #wk as int
declare #endwk as datetime
declare #tbl as table (
tbl_wk int,
tbl_Monday datetime
)
set #endwk= (SELECT DATEPART(wk, GETDATE())+1)
set #wk = 1
set #year = '2017'
set #startdate = CAST (cast(#year as varchar(4))+ '/01/01 00:00:00' as datetime)
while (#wk < #endwk)
begin
insert into #tbl (tbl_wk,tbl_Monday)
select #wk,DATEADD(wk, DATEDIFF(wk,0,#startdate), 0) as monday--MondayOfCurrentWeek,
set #wk = #wk+1
set #startdate = #startdate+7
end
select * from #tbl
You could adapt this to create a table in SQL and then reference this in your report.
Note: You could include Year in an outer loop if you need dates from more than one year
declare #year as int
declare #startdate as datetime
declare #wk as int
declare #tbl as table (
tbl_wk int,
tbl_Monday datetime
)
set #wk = 1
set #year = '2017'
set #startdate = CAST (cast(#year as varchar(4))+ '/01/01 00:00:00' as datetime)
while (#wk < 53)
begin
insert into #tbl (tbl_wk,tbl_Monday)
select #wk,DATEADD(wk, DATEDIFF(wk,0,#startdate), 0) as monday--MondayOfCurrentWeek,
set #wk = #wk+1
set #startdate = #startdate+7
end
select * from #tbl

Convert postgresql trigger to mysql trigger

I'm trying to transpose a postgres trigger to a mysql trigger. It automatically adds fields to the row according to the date added
CREATE FUNCTION convert_date ()
RETURNS trigger
AS $$
declare
date_min DATE;
date_max DATE;
temp_year INTEGER;
begin
SELECT SUBSTRING(NEW."dc_date_label",0,5)::integer
INTO temp_year;
SELECT date(temp_year || '-01-10')
INTO date_min;
SELECT date(temp_year +1 || '-09-30')
INTO date_max;
NEW."dc_date_start" = date_min;
NEW."dc_date_end" = date_max;
RETURN new;
end;
CREATE TRIGGER trig_b_i_compute_date()
BEFORE INSERT
ON campaigns
FOR EACH ROW
EXECUTE PROCEDURE convert_date();
This is what i've done on mysql :
DELIMITER //
CREATE TRIGGER trig_b_i_compute_date
BEFORE INSERT ON campaigns
FOR EACH ROW
BEGIN
DECLARE date_min DATE;
DECLARE date_max DATE;
DECLARE temp_year INTEGER;
SET temp_year = SELECT CONVERT( SUBSTRING(NEW.dc_date_label,1,5), UNSIGNED INTEGER) ;
SET date_min = SELECT CONVERT( CONCAT(temp_year,'-01-10'), DATE);
SET date_max = SELECT CONVERT( CONCAT(temp_year + 1, '09-30'), DATE);
SET NEW.dc_date_start = date_min;
SET NEW.dc_date_end = date_max;
END;
//
DELIMITER ;
However I get an error :
MySQL server version for the right syntax to use near 'SELECT CONVERT( SUBSTRING(NEW.dc_date_label,1,5), UNSIGNED INTEGER) ;
What is wrong with the procedure ?
If you use SELECT in a SET statement, you need to put it in parentheses:
SET temp_year = (SELECT ...);
But in your case you don't need a SELECT and you can just skip it:
SET temp_year = CONVERT(...);
You can also use the SELECT INTO syntax in MySQL:
SELECT CONVERT(...) INTO temp_year;
And there is no need to declare date_min and date_max. Also no need to cast everything explicitly. Your trigger body could be:
DECLARE temp_year INTEGER;
SET temp_year = CONVERT( SUBSTRING(NEW.dc_date_label,1,5), UNSIGNED);
SET NEW.dc_date_start = CONCAT(temp_year, '-01-10');
SET NEW.dc_date_end = CONCAT(temp_year + 1, '-09-30');
I don't know how dc_date_label looks like, and why the year should be 5 characters long. So I kept the year extraction as it is. But if it's a DATE, DATETIME or TIMESTAMP, you can just use the YEAR function:
SET temp_year = YEAR(NEW.dc_date_label);
And since it's much shorter, you could also use it inline and skip the temp_year variable:
SET NEW.dc_date_start = CONCAT(YEAR(NEW.dc_date_label), '-01-10');
SET NEW.dc_date_end = CONCAT(YEAR(NEW.dc_date_label) + 1, '-09-30');
And last one: Remove the semicolon after END. It might work, but it doesn't belong there.

Update and Insert table rows using a Mysql stored procedure

I have a table book_meetings which have 70000 record and I want to migrate this data into another table with little modification for this I have created a Mysql stored procedure. Records are inserted in new table but values are set as null.
I am selecting only four columns from book_meetings table and wants to insert them in table.
id int
date date
meet_at time
duration_in_hours decimal
What I want is calculate the start_date and end_date based on above values.
For example:
if date ="2017-09-08" , meet_at is "09:00:00" and duration_in_hours is 1.5
then start_date will be "2017-09-08 09:10:00"
end_date= start_date_duration_in_hour
end_date will be "2017-09-08 09:10:00"
start_date = concat date and meet_at
end_date = start_date + duration_in_hours
and insert this values in new table
if there is another better idea then please suggest
CREATE PROCEDURE book_meetings8()
BEGIN
-- Declare local variables
DECLARE done BOOLEAN DEFAULT 0;
DECLARE meet_at TIME;
DECLARE start_date DATETIME;
DECLARE tmp_date VARCHAR(255);
DECLARE end_date DATETIME;
DECLARE end_recurring_date DATE;
DECLARE date1 DATE ;
DECLARE id INTEGER(11);
DECLARE duration DECIMAL(8,2);
DECLARE minutes INTEGER(11);
-- Declare the cursor
DECLARE iter CURSOR
FOR
SELECT id,date, meet_at,duration_in_hours FROM
book_meetings LIMIT 100;
-- Declare continue handler
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
-- Open the cursor
OPEN iter;
-- Loop through all rows
REPEAT
-- Get order number
FETCH iter INTO id,date1,meet_at,duration;
SET minutes = duration * 60;
SET start_date = CAST(date1 as char) + " "+CAST(meet_at as
char);
SET end_date = CAST(start_date as datetime) + INTERVAL
minutes MINUTE;
INSERT INTO
book_meetings_1(start_date,end_date)
VALUES(start_date,end_date);
-- End of loop
UNTIL done END REPEAT;
-- Close the cursor
CLOSE iter;
END;
Well I have solved above problem with single SQL statement (Insertion and updation all record at once without store procedure)
INSERT INTO temp_diary.book_meetings ( id,start_date,end_date) SELECT id,CONCAT(`date`, ' ', `meet_at`) as start_date,DATE_ADD(concat(date,' ',meet_at), INTERVAL `duration_in_hours` HOUR) as end_date FROM estate.book_meetings;

I have a table with a set of data and I would want to display specific records from it using Mysql:

Here is the table: Sorry couldn't depict the table properly here.
Id Date1 Rank1 date2 Rank2
100 1/1/01 1 1/2/01 1
100 1/2/01 1 1/3/01 1
100 1/3/01 1 1/5/01 4
Now, I would want to see the result where the rank changes but the date1 should display the date from which Rank = 1 started,
An output like this:
Id Date1 Rank1 date2 Rank2
100 1/1/01 1 1/5/01 4
Can anyone please let me know how to go about doing this in MYSQL? I thought about using SQL cursor.Is there another way?
I will create a stored procedure and a cursor to iterate through each record.
My stored procedure will look as follows:
CREATE PROCEDURE `GetChangedRank`()
BEGIN
# Variables containing the final result
DECLARE ID INTEGER;
DECLARE DATE1 DATE;
DECLARE Rank1 INTEGER;
DECLARE DATE2 DATE;
DECLARE Rank2 INTEGER;
DECLARE ROWNUM INTEGER DEFAULT 0;
# Temporary variables to store values of each row.
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE ID_VALUE INT;
DECLARE DATE1_VALUE DATE;
DECLARE Rank1_VALUE INT;
DECLARE DATE2_VALUE DATE;
DECLARE Rank2_VALUE INT;
# testtable is the table that contains data
DECLARE RECORDS_CURSOR CURSOR FOR SELECT * FROM testtable;
# To check if we reached the end of the result set
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1;
# Open cursor
OPEN RECORDS_CURSOR;
# Loop to fetch one row at a time
get_records: LOOP
# Fetch row values to different variables
FETCH RECORDS_CURSOR INTO ID_VALUE, DATE1_VALUE, Rank1_VALUE, DATE2_VALUE, Rank2_VALUE
# To track the row number
SET ROWNUM = ROWNUM + 1;
# Quit the loop when the end of resultset is reached.
IF v_finished = 1 THEN
LEAVE get_records;
END IF;
# Assign the first row values to the final values. Date2 and Rank2 will be updated when the rank is changed.
IF ROWNUM = 1 THEN
BEGIN
SET ID = ID_VALUE;
SET DATE1 = DATE1_VALUE;
SET Rank1 = Rank1_VALUE;
SET DATE2 = DATE2_VALUE;
SET Rank2 = Rank2_VALUE;
END;
ELSE
BEGIN
# Date2 and Rank2 is updated with the row values as the rank is changed.
IF Rank1_VALUE != Rank2_VALUE THEN
BEGIN
SET DATE2 =DATE2_VALUE;
SET Rank2 = Rank2_VALUE;
END;
END IF;
END;
END IF;
END LOOP get_records;
# Select the final values
SELECT ID, DATE1, Rank1, DATE2, Rank2;
# Close cursor
CLOSE RECORDS_CURSOR;
END
Once the procedure is created, you can run this procedure as follow
CALL GetChangedRank;
Is this what you want?
SELECT * FROM <table name>
WHERE Rank1 <> Rank2
Try this nested query
Select Id, (select Date1 from TableName group by Rank1) as Date1, Rank1, Date2, Rank2 from TableName where Rank1<>Rank2;

Check Each Date In Date Range

In SQL Server 2008 I have a startdate and an enddate being passed to my procedure. I need to check each date in the range to see if it exists in my validworkday table. I have no clue where to begin on this, but this is how start/end day are set-up
Declare #startdate date, #enddate date
Set #startdate = '01/01/2015'
Set #enddate = '04/16/2015'
Now how can I iterate each date in this span to see if validworkday = true for it? The check I would need to run is like so (checking each date)
Select isvalidworkday
from validworkdays
where date = '01/01/2015'
Select isvalidworkday
from validworkdays
where date = '01/02/2015'
This is syntax that I found from #Incidently years ago (I don't remember where that original post is, but hopefully this will be enough to give the credit), that I still use today. All I did was slightly tweak his syntax to insert the data into a temp table and add a cursor to iterate each individual date.
DECLARE #DateFrom smalldatetime, #DateTo smalldatetime, #firstdate date;
SET #DateFrom='20000101';
SET #DateTo='20081231';
-------------------------------
WITH T(date)
AS
(
SELECT #DateFrom
UNION ALL
SELECT DateAdd(day,1,T.date)
FROM T
WHERE T.date < #DateTo
)
SELECT date
INTO #AllDates
FROM T OPTION (MAXRECURSION 32767);
Declare c1 Cursor For
Select date
FROM #AllDates
Open c1
Fetch Next From c1 Into #firstdate
While ##FETCH_STATUS = 0
Begin
--Do whatever processing you need here
Fetch Next From c1 Into #firstdate
End
Close c1
Deallocate c1
Code should only live in one place and not be rewritten. Create functions (once) like GetAllIntsBetween(), GetAllMonths(), GetAllDates(), etc. Then used them like:
DECLARE #startdate date = '01/01/2015', #enddate date = '04/16/2015'
SELECT allDates.TheDate,
isnull(v.isvalidworkday, false) AS isvalidworkday
FROM dbo.GetAllDates(#startdate, #enddate) AS allDates
LEFT JOIN validworkdays AS v
ON allDates.TheDate = v.MyDate
The GetAllDates() would be:
CREATE FUNCTION dbo.GetAllDates(#Start DATETIME, #End DATETIME)
RETURNS
#AllDates TABLE
(
TheDate DATETIME
)
AS
BEGIN
IF #Start > #End
BEGIN
DECLARE #Temp DATETIME
SET #Temp = #Start
SET #Start = #End
SET #End = #Temp
END
WHILE #Start <= #End
BEGIN
INSERT INTO #AllDates
VALUES(#Start)
SET #Start = DATEADD(DAY, 1, #Start)
END
RETURN
END
(note: can change DATETIME to DATE)