MySQL: Creating regr_slope function - mysql

In MySQL I have added this function to calculate slope:
DELIMITER $$
CREATE FUNCTION regr_slope(x float, y float)
RETURNS float
DETERMINISTIC
BEGIN
DECLARE n int;
DECLARE sum_x float;
DECLARE sum_y float;
DECLARE sum_xx float;
DECLARE sum_xy float;
DECLARE slope float;
SET n = COUNT(x);
SET sum_x = SUM(x);
SET sum_y = SUM(y);
SET sum_xx = SUM(x*x);
SET sum_xy = SUM(x*y);
SET slope = (n * sum_xy - sum_x * sum_y) / (n * sum_xx - POWER(sum_x, 2));
RETURN slope;
END$$
DELIMITER ;
However, when I use it like this:
SELECT regr_slope(pd.avg_velocity, pd.load_kg) FROM push_data
I get the error Invalid use of group function.
What could be the reason for this?

Related

Multiple select statements in same function

I have the following function:
DELIMITER $$
create function fp_v2.fp_splitadjprice (id char(8), startdate date)
returns float
begin
declare splitfactor float;
declare splitadjprice float;
declare spinofffactor float;
set splitfactor = 1.0;
select splitfactor = fp_v2.fp_splitfactor_prices(id, startdate);
select splitadjprice = convert(float,p_price * splitfactor)
from fp_v2.fp_basic_prices p
where fsym_id = id and p_date = startdate;
return splitadjprice;
END$$
DELIMITER ;
I get an error message at the 2nd select statement saying "expected a ( or with".
I really don't understand the syntax of MySQL workbench. It seems pretty random to me. Like when should I put ; and when should I not?. What are the rules?
You need use SELECT .. INTO to update your variables.
convert sintaxis is CONVERT(value, type) and you cant use FLOAT as type need use DECIMAL and you probably dont need it anyway because your both variable are float already.
DELIMITER $$
create function fp_v2.fp_splitadjprice (id char(8), startdate date)
returns float
begin
declare splitfactor float;
declare splitadjprice float;
declare spinofffactor float;
set splitfactor = 1.0;
SELECT fp_v2.fp_splitfactor_prices(id, startdate) INTO splitfactor ;
SELECT convert(p_price * splitfactor, DECIMAL (10,4) INTO splitadjprice
FROM fp_v2.fp_basic_prices p
WHERE fsym_id = id and p_date = startdate;
return splitadjprice;
END$$
DELIMITER ;

convert TSQL query to MySQL

I need to convert this tSQL query into MySQL query version 5.7.14
I tried declare parameter with the following syntax
declare #commissionType INT;
but I reached a dead end and need help to convert this query
CREATE PROCEDURE MyProc
#chainId int
as
BEGIN
declare #commissionMethod int
declare #commissionType int
declare #value decimal(18,2)
set #commissionMethod = 1
set #value = 200000
set #commissionType = (select CommissionType from CommissionRules
where ChainId = #chainId )
IF(#commissionMethod = 1)
BEGIN
print('alert')
select (Fixed * #value) / 100 from CommissionRules where ChainId = #chainId
END
END
This is pretty much a literal conversion. But check your logic. It doesn't make any sense. v_commissionMethod is always 1 and v_commissionType is not even being used after selecting a value.
DELIMITER //
CREATE PROCEDURE MyProc (
p_chainId int)
BEGIN
declare v_commissionMethod int;
declare v_commissionType int;
declare v_value decimal(18,2);
set v_commissionMethod = 1;
set v_value = 200000;
select CommissionType into v_commissionType from CommissionRules
where ChainId = p_chainId ;
IF(v_commissionMethod = 1)
THEN
/* print('alert') */
select (Fixed * v_value) / 100 from CommissionRules where ChainId = p_chainId;
END IF;
END;
//
DELIMITER ;
Something like this:
DELIMITER $$
CREATE PROCEDURE MyProc (
in_chainId unsigned
) as
BEGIN
select v_CommissionType := CommissionType,
v_commissionMethod = 1,
v_value = 200000
from CommissionRules
where ChainId = in_chainId;
if v_commissionMethod = 1 then
select 'alert';
select (Fixed * v_value) / 100
from CommissionRules
where ChainId = in_chainId
end if;
END;$$
DELIMITER ;

How to set variable values for different statement for same NOT FOUND SQL EXCEPTION in STORE PROCEDURE

I Have A Procedure Where I need to set d_x FOR select statement 1, d_y FOR select statement 2, d_z for select statement 3. How could i modify below procedure to achieve that ...
CREATE PROCEDURE A ()
BEGIN
DECLARE d_a INT;
DECLARE d_b INT;
DECLARE d_c INT;
---
--
-
DECLARE CONTINUE HANDLER FOR NOT FOUND
BEGIN
SET d_x = 1;
SET d_y = 2;
SET d_z = 3;
END;
SELECT aa INTO d_x FROM TEST1;
SELECT bb INTO d_y FROM TEST2;
SELECT cc INTO d_z FROM TEST3;
END
I found One Solution for My Problem. And Probable Answer. But If there any more alternative ways please define.
CREATE PROCEDURE A ()
BEGIN
DECLARE d_a INT;
DECLARE d_b INT;
DECLARE d_c INT;
---
--
-
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND
BEGIN
SET d_x = 1;
END;
SELECT aa INTO d_x FROM TEST1;
END;
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND
BEGIN
SET d_y = 2;
END;
SELECT bb INTO d_y FROM TEST2;
END;
BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND
BEGIN
SET d_y = 2;
END;
SELECT cc INTO d_z FROM TEST3;
END;
END

MySQL Function for calculating Haversine Distance

all.
I want to create a mysql function that calculates the haversine distance between two geo-code.
CREATE FUNCTION haversineDistance
(
lat1 VARCHAR(256),
long1 VARCHAR(256),
lat2 VARCHAR(256),
long2 VARCHAR(256)
)
RETURNS FLOAT DETERMINISTIC
BEGIN
DECLARE radLat1 FLOAT;
DECLARE radLong1 FLOAT;
DECLARE radLat2 FLOAT;
DECLARE radLong2 FLOAT;
DECLARE dLat FLOAT;
DECLARE dLong FLOAT;
DECLARE cordLength FLOAT;
DECLARE centralAngle FLOAT;
DECLARE distance FLOAT;
SET radLat1 = CAST(lat1 AS FLOAT) * PI() / 180;
SET radLong1 = CAST(long1 AS FLOAT) * PI() / 180;
SET radLat2 = CAST(lat2 AS FLOAT) * PI() / 180;
SET radLong2 = CAST(long2 AS FLOAT) * PI() / 180;
SET dLat = radLat2 - radLat1;
SET dLong = radLong2 - radLong2;
SET cordLength = POW(SIN(dLat/2),2)+COS(lat1)*COS(lat2)*POW(SIN(dLon/2),2);
SET centralAngle = 2 * ATAN2(SQRT(cordLength), SQRT(1-cordLength));
SET distance = 6367 * centralAngle;
RETURN distance;
END
But I got an error like this;
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 '' at line 4
Anyone has an idea?
Thank you in advance.
Okay.
Solved it.
DELIMITER $$
CREATE FUNCTION haversineDistance
(
lat1 VARCHAR(256),
long1 VARCHAR(256),
lat2 VARCHAR(256),
long2 VARCHAR(256))
RETURNS FLOAT DETERMINISTIC
BEGIN
DECLARE radLat1 FLOAT;
DECLARE radLong1 FLOAT;
DECLARE radLat2 FLOAT;
DECLARE radLong2 FLOAT;
DECLARE dLat FLOAT;
DECLARE dLong FLOAT;
DECLARE cordLength FLOAT;
DECLARE centralAngle FLOAT;
DECLARE distance FLOAT;
SET radLat1 = CAST(lat1 AS DECIMAL(10,10)) * PI() / 180;
SET radLong1 = CAST(long1 AS DECIMAL(10,10)) * PI() / 180;
SET radLat2 = CAST(lat2 AS DECIMAL(10,10)) * PI() / 180;
SET radLong2 = CAST(long2 AS DECIMAL(10,10)) * PI() / 180;
SET dLat = radLat2 - radLat1;
SET dLong = radLong2 - radLong2;
SET cordLength = POW(SIN(dLat/2),2)+COS(lat1)*COS(lat2)*POW(SIN(dLon/2),2);
SET centralAngle = 2 * ATAN2(SQRT(cordLength), SQRT(1-cordLength));
SET distance = 6367 * centralAngle;
RETURN distance;
END
Right now, you're getting an error, due to the semi-colon characters present as line delimiter in your function.
To explain it further, directly quoting from MySQL documentation
By default, mysql recognizes the semicolon as a statement delimiter,
so you must redefine the delimiter temporarily to cause mysql to pass
the entire stored program definition to the server.
This means that you must override the default delimiter temporarily for your program to compile. Enacapsulate your program between
DELIMITER $$
your code for function
$$
and then give it a try.
EDIT:
You can change back the delimiter by specifying the default delimiter again
mysql> DELIMITER ;

MySQL build a variable name?

I am trying to build a variable name dynamically within a user defined function but it seems it does not work. Is there a way to do this or by using an array variable?
I have a string of 7 characters which represents the days of the week (1234567, or 1_3_5_7, etc.). I would like evaluate how often during a week a day is selected (from 0 to 7). I thought, it would be easiest to use a loop to go through all the 7 positions but I get an error message saying
[Err] 1193 - Unknown system variable 'CONCAT'
Any hints on how I can achieve that? This is my code:
DELIMITER $$
DROP FUNCTION IF EXISTS fn_freq$$
CREATE FUNCTION fn_freq(days INT) RETURNS INT
BEGIN
DECLARE D1 VARCHAR(1);
DECLARE D2 VARCHAR(1);
DECLARE D3 VARCHAR(1);
DECLARE D4 VARCHAR(1);
DECLARE D5 VARCHAR(1);
DECLARE D6 VARCHAR(1);
DECLARE D7 VARCHAR(1);
DECLARE x INT;
DECLARE fn_freq INT;
SET x =1;
SET fn_freq = 0;
WHILE x < 8 DO
SET CONCAT('D',x) = MID(days, x, 1);
IF CONCAT('D',x) = '_' THEN
ELSE
SET fn_freq = fn_freq + 1;
SET x = x + 1;
END IF;
SET x = x + 1;
END WHILE;
RETURN fn_freq;
END$$
DELIMITER ;
You cant SET CONCAT as in SET CONCAT('D',x) = MID(days, x, 1) what instead i think will be better to declare & set the concat value to that variable and use that variable for the IF condition. Also I think you missed out what have to be done in the case IF Condition is true.
Thanks for your reply. I got it to work like this, but I am still curious, how I could dynamically create a variable in some other cases.
For this function, I realized I don't even need the variable, as I can evaluate it straight in the if clause.
DELIMITER $$
DROP FUNCTION IF EXISTS fn_freq$$
CREATE FUNCTION fn_freq(days VarChar(7)) RETURNS INT
BEGIN
DECLARE x INT;
DECLARE fn_freq INT;
SET x =1, fn_freq = 0;
WHILE x < 8 DO
IF MID(days, x, 1) <> '_' THEN
SET fn_freq = fn_freq + 1;
END IF;
SET x = x + 1;
END WHILE;
RETURN fn_freq;
END$$
DELIMITER ;