I am working in joomla. And I have huge amount of data in mySql table. I need a calculation for the project with all this data. As the result will vary every time, I am using MySql PROCEDURE to execute the calculation.
In the PROCEDURE I am first working the calculation, then inserting the data in a temporary table (tmp_zipcode), then fetching it. Its all working fine. But I need to fetch it directly after calculation. I do not want to insert the data to temporary table then fetch it every time.
The following is a procedure call in mySql. However, I think, you don't need to go through below whole PROCEDURE code to answer this question.
DELIMITER $$
DROP FUNCTION IF EXISTS `GetDistance`$$
CREATE FUNCTION `GetDistance`(
lat1 numeric (9,6),
lon1 numeric (9,6),
lat2 numeric (9,6),
lon2 numeric (9,6)
) RETURNS decimal (10,5)
BEGIN
DECLARE x decimal (20,10);
DECLARE pi decimal (21,20);
SET pi = 3.14159265358979323846;
SET x = sin( lat1 * pi/180 ) * sin( lat2 * pi/180 ) + cos(
lat1 *pi/180 ) * cos( lat2 * pi/180 ) * cos( abs ( (lon2 * pi/180) -
(lon1 *pi/180) ) );
SET x = atan( ( sqrt( 1- power( x, 2 ) ) ) / x );
RETURN ( 1.852 * 60.0 * ((x/pi)*180) ) / 1.609344;
END $$
DELIMITER ;
DELIMITER $$
DROP PROCEDURE IF EXISTS `GetNearbyZipCodes`$$
CREATE PROCEDURE `GetNearbyZipCodes`(
zipbase varchar (6),
rang numeric (15)
)
BEGIN
DECLARE lat1 decimal (5,2);
DECLARE long1 decimal (5,2);
DECLARE rangeFactor decimal (7,6);
SET rangeFactor = 0.014457;
SELECT Latitude,Longitude into lat1,long1 FROM ZIPCodes WHERE ZipCode = zipbase;
Insert into tmp_zipcode(zipcode,radius) SELECT B.ZipCode,GetDistance(lat1,long1,B.Latitude,B.Longitude) FROM ZIPCodes AS B WHERE B.Latitude BETWEEN lat1-(rang*rangeFactor) AND lat1+(rang*rangeFactor) AND B.Longitude BETWEEN long1-(rang*rangeFactor) AND long1+(rang*rangeFactor) AND GetDistance(lat1,long1,B.Latitude,B.Longitude) <= rang;
END $$
DELIMITER ;
The following is joomla code which I am using to call the PROCEDURE. Here first I am truncating the temp table and then calling the PROCEDURE in which it inserts data. Then I fetch it again.
$truncate="truncate table tmp_zipcode";
$db->setquery($truncate);
$db->query();
$test="CALL GetNearbyZipCodes( $zipcode ,$miles)";
$db->setquery($test);
$re=$db->query();
$result_codes_query="select zipcode,radius from tmp_zipcode";
$db->setquery($result_codes_query);
$db->query();
$codes=$db->loadAssocList();
So I need to fetch the calculation part directly, without inserting to, and fetching from temp table. I do not want to use a temp table at all. How I can fetch data from MySql PROCEDURE in joomla ?
Related
I was never good in math, so I need help how to convert linear value to dB.
First I show you how I calculated the linear value from -24dB.
var dB, linearLevel: integer;
begin
dB := -24;
linearLevel := Round( 1/exp( 2.30258509299 * (abs(dB)/20) ) *32767);
end;
Where 1/exp( 2.30258509299 * (abs(-24)/20) ) ; is normalized value.
For conversion to sample value I use 1/exp(...)*32767
My problem is here: conversion back
I was told to use formula 20*log10(linearLevel). So I tried to create it but my result is 18 instead 24 (or -24) dB.
linearValue := 2067; // the result of the formula above
db := round( exp( 20*2.30258509299*(linearLevel / 32767) ) );
How to calculate the dB?
If
linearLevel := Round( 1/exp( 2.30258509299 * (abs(dB)/20) ) * 32767);
we lose information due to the rounding (in the language of mathematics, the Round function is not injective). So given a linearLevel value, it is impossible to get back the original dB value. Therefore, let us consider
linearLevel := 1/exp( 2.30258509299 * (abs(dB)/20) ) * 32767;
instead. This implies
linearLevel / 32767 := 1/exp( 2.30258509299 * (abs(dB)/20) )
and
32767 / linearLevel := exp( 2.30258509299 * (abs(dB)/20) )
and
ln(32767 / linearLevel) := 2.30258509299 * (abs(dB)/20)
and
ln(32767 / linearLevel) / 2.30258509299 := abs(dB)/20
and
20 * ln(32767 / linearLevel) / 2.30258509299 := abs(dB).
Here we again have an issue, since the absolute value function is not injective. If abs(dB) is 7, we cannot possibly tell if dB is 7 or -7.
But if we assume that dB is non-positive, we finally have
dB = -20 * ln(32767 / linearLevel) / 2.30258509299.
Simplifications
Since 2.30258509299 is ln(10), this is
dB = -20 * ln(32767 / linearLevel) / ln(10).
But log10(x) = ln(x) / ln(10), so we can write
dB = -20 * Log10(32767 / linearLevel)
where the Log10 function is found in the Math unit.
Also, using the law a log(b) = log(b^a) in the case a = -1, we can even write
dB = 20 * Log10(linearLevel / 32767).
My field values are like:
810.9 MB
1.2 GB
395.1 MB
982.3 MB
7.7 GB
149.4 MB
10.0 GB
429.1 MB
3.1 GB
and I want to sum this column in gb in my ASP.NET MVC controller.
But I have no idea how to do this.
You could try something like this:
-- This is your "raw" input - just all the strings in your example
DECLARE #input TABLE (Measure VARCHAR(50))
INSERT INTO #input ( Measure )
VALUES ('810.9 MB'), ('1.2 GB'), ( '395.1 MB'), ( '982.3 MB'), ( '7.7 GB'), ( '149.4 MB'), ( '10.0 GB'), ( '429.1 MB'), ( '3.1 GB')
-- Now declare a separate table that contains (1) the raw value, (2) the contained *numerical* value, and (3) the unit of measure
DECLARE #Storage TABLE (Measure VARCHAR(50), NumValue DECIMAL(20,4), Unit VARCHAR(10))
-- Fill your raw input into that "working table"
INSERT INTO #Storage (Measure, NumValue, Unit)
SELECT
Measure,
NumMeasure = CAST(SUBSTRING(Measure, 1, CHARINDEX(' ', Measure)) AS DECIMAL(20, 2)),
Unit = SUBSTRING(Measure, CHARINDEX(' ', Measure) + 1, 9999)
FROM
#input
SELECT * FROM #Storage
-- when you select from that "working" table, you can now easily *SUM* the numerical values,
-- and show them on screen whichever way you want - as "xxx MB" or "yyyy GB" or whatever - up to you
SELECT
SUM(CASE Unit
WHEN 'MB' THEN NumValue * 1000000
WHEN 'GB' THEN NumValue * 1000000000
ELSE NumValue
END),
CAST(SUM(CASE Unit
WHEN 'MB' THEN NumValue * 1000000
WHEN 'GB' THEN NumValue * 1000000000
ELSE NumValue
END) / 1000000000.0 AS VARCHAR(25)) + ' GB'
FROM
#Storage
Update:
If you want to do this in C# code, try this:
foreach(var item in list)
{
// split "item" into two parts
string[] parts = item.Split(' ');
// parts[0] should be a decimal value
decimal numValue = 0.0m;
if (decimal.TryParse(parts[0], out numValue))
{
decimal convertedValue = 0.0m;
if(parts[1] == "MB")
{
convertedValue = numValue * 1000000;
}
else if (parts[1] == "GB")
{
convertedValue = numValue * 1000000000;
}
}
}
I've been trying to resolve this since a while, still couldn't figure out how to apply a while value like:
while ....(having values in (X1, X2, X3, ........)
(
execute 'package....'
Param = X
)
passing every time the one of the values of X, X1 then X2 and so on.
You can pass all params to temporary table and then loop them using WHILE:
CREATE TABLE #tab(id INT IDENTITY(1,1), param_value NVARCHAR(MAX));
INSERT INTO #tab(param_value)
VALUES (#X1), (#X2), (#X3); -- ...
DECLARE #counter INT = 1,
#param NVARCHAR(MAX);
WHILE #counter <= (SELECT MAX(id) FROM #tab)
BEGIN
SELECT #param = param_value
FROM #tab
WHERE id = #counter;
EXEC [dbo].[my_stored_proc]
#param;
SET #counter += 1;
END
SqlFiddleDemo
I am new to DB2 queries.
Here, I am passing a comma separated value as an IN parameter in a Stored Procedure. I want to search on the basis of those values.
Select * from USER where user_id in (IN_User);
Here, IN_User will have values of the kind ('val1','val2','val3')
It should return all the rows which has val1 or val2 or val3 as the User_id. As much as I know this can be done using UDF but I want to know is there any other way to do it without UDF.
please create a function to split the comma separated string
Please see the below function
CREATE FUNCTION StringToRows(
cString1 CLOB (10 M) ,
cStringSplitting1 VARCHAR(10) )
RETURNS TABLE (Lines VARCHAR(500))
SPECIFIC StringToRows_Big
DETERMINISTIC
NO EXTERNAL ACTION
CONTAINS SQL
BEGIN ATOMIC
DECLARE cStringSplitting VARCHAR(10);
DECLARE LenSplit SMALLINT;
SET cStringSplitting = cStringSplitting1;
SET LenSplit = LENGTH(cStringSplitting);
IF LENGTH(TRIM(cStringSplitting)) = 0 THEN
SET cStringSplitting = ' ', LenSplit = 1 ;
END IF ;
RETURN WITH
TEMP1 ( STRING) as (values (cString1) ),
TEMP2 ( Lines, STRING_left) as
(SELECT
SUBSTR(STRING,1, CASE WHEN LOCATE(cStringSplitting, STRING) = 0 THEN LENGTH(STRING) ELSE LOCATE(cStringSplitting,STRING) - 1 END),
(CASE WHEN (LOCATE(cStringSplitting, STRING) = 0) THEN '' ELSE SUBSTR(STRING, LOCATE(cStringSplitting,STRING) + LenSplit) END)
FROM TEMP1 WHERE LENGTH(STRING) > 0
UNION ALL
SELECT
SUBSTR(STRING_left,1, CASE LOCATE(cStringSplitting,STRING_left) WHEN 0 THEN LENGTH(STRING_left) ELSE LOCATE(cStringSplitting,STRING_left) - 1 END),
(CASE WHEN LOCATE(cStringSplitting,STRING_left) = 0 THEN '' ELSE SUBSTR(STRING_left, LOCATE(cStringSplitting,STRING_left) + LenSplit) END)
FROM TEMP2 WHERE LENGTH(STRING_left) > 0 )
SELECT Lines FROM TEMP2;
END
please see the sample stored procedure to call the function
CREATE PROCEDURE TEST_USR(IN #inputParam CLOB (10 M))
SPECIFIC TEST_USR
DYNAMIC RESULT SETS 1
P1: BEGIN
DECLARE CURSOR1 CURSOR WITH RETURN FOR
Select * from USER where user_id IN (SELECT * FROM TABLE(StringToRows(#inputParam, ',')) AS test);
OPEN CURSOR1;
END P1
I'm having trouble creating this stored procedure on IBM Informix Dynamic Server Version 10.00.FC9 (see Jonathan Leffler's answer to this post here) using the 'isql' command from Informix SQL.
I get an error on the ( char for each of his two examples near RETURNING CHAR(8)
ex. 1:
CREATE PROCEDURE ampm_time(tm SMALLINT) RETURNING CHAR(8);
DEFINE hh SMALLINT;
DEFINE mm SMALLINT;
DEFINE am SMALLINT;
DEFINE m3 CHAR(3);
DEFINE a3 CHAR(3);
LET hh = MOD(tm / 100 + 11, 12) + 1;
LET mm = MOD(tm, 100) + 100;
LET am = MOD(tm / 1200, 2);
LET m3 = mm;
IF am = 0
THEN LET a3 = ' am';
ELSE LET a3 = ' pm';
END IF;
RETURN (hh || ':' || m3[2,3] || a3);
END PROCEDURE;
ex. 2:
CREATE PROCEDURE ampm_time(tm SMALLINT) RETURNING CHAR(8);
DEFINE i2 SMALLINT;
DEFINE hh SMALLINT;
DEFINE mm SMALLINT;
DEFINE am SMALLINT;
DEFINE m3 CHAR(3);
DEFINE a3 CHAR(3);
LET i2 = tm / 100;
LET hh = MOD(i2 + 11, 12) + 1;
LET mm = MOD(tm, 100) + 100;
LET i2 = tm / 1200;
LET am = MOD(i2, 2);
LET m3 = mm;
IF am = 0
THEN LET a3 = ' am';
ELSE LET a3 = ' pm';
END IF;
RETURN (hh || ':' || m3[2,3] || a3);
END PROCEDURE;
They were designed by Jonathan Leffler (Informix Magician extraordinaire) in an effort to resolve the question I asked in the linked post. The intended return is to convert an INT datatype holding military time into a 2:30 pm type format.
This problem is DB-Access vs ISQL.
ISQL has a warped sense of humour and thinks that the syntax of SQL still matches what was current with Informix OnLine 4.10 (or, in those days, INFORMIX-OnLine 4.10). Specifically, it doesn't know that stored procedures are made up of multiple statements separated by semi-colons and mis-assumes that SQL statements end at the first semi-colon not in a string or comment.
Workarounds:
Use DB-Access instead of ISQL to create stored procedures.
Obtain SQLCMD from the IIUG Software Archive and use that instead.
Use 'mkproc' from the SQLCMD software to create stored procedures.
Of these, the easiest is to use DB-Access (aka dbaccess - found in $INFORMIXDIR/bin where the server software lives).