Why does query give different result once put into stored procedure? - mysql

I have read a few articles listed below to try and find an answer to my problem. They both seemed to have the same issue.
I saw this one but I read in the MySQL documentation that all procedures are by default non deterministic.
This one doesn't have anything to do with my problem because its SQL Server (not MySQL).
Here is the query I am using to create my procedure:
CREATE PROCEDURE getcusbyzip(zipcode VARCHAR(30),radius VARCHAR(30))
SELECT C.CustomerName, C.MenuId
FROM Customers C
INNER JOIN (
SELECT ZIPCODE, ( 3959 * ACOS( COS( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) * COS( RADIANS( LAT ) ) * COS( RADIANS( LNG ) - RADIANS( (
SELECT Z.LNG
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) + SIN( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) * SIN( RADIANS( LAT ) ) ) ) AS distance
FROM ZipCodes
HAVING distance <radius
ORDER BY distance
LIMIT 0 , 20
) AS RelevantCodes ON ( C.ZIPCODE = RelevantCodes.ZIPCODE )
Now If I run this query after that one:
CALL getcusbyzip(08360,50)
I get zero rows returned. But if I run the exact same statement inside the procedure as just a query and put the params in like this:
SELECT C.CustomerName, C.MenuId
FROM Customers C
INNER JOIN (
SELECT ZIPCODE, ( 3959 * ACOS( COS( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =08360
LIMIT 0 , 1
) ) ) * COS( RADIANS( LAT ) ) * COS( RADIANS( LNG ) - RADIANS( (
SELECT Z.LNG
FROM ZipCodes Z
WHERE Z.ZIPCODE =08360
LIMIT 0 , 1
) ) ) + SIN( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =08360
LIMIT 0 , 1
) ) ) * SIN( RADIANS( LAT ) ) ) ) AS distance
FROM ZipCodes
HAVING distance <50
ORDER BY distance
LIMIT 0 , 20
) AS RelevantCodes ON ( C.ZIPCODE = RelevantCodes.ZIPCODE )
I get exactly what I wanted. The answer should only be one row but why is the result coming to me while not in a procedure but when I put it in one it will not give me the row.
I thought maybe it was because I did not have BEGIN and END but when I place that after the create line and END after the last line it fails to produce the procedure.

Your sample code and stored procedure code are too different from one another.
In order to identify your problem, you need to do the following
At the top of your sample code (not SP)
Declare a variable called zipcode of type varchar(30)
Declare a variable called radius of type varchar(30)
Then, modify the rest of the sample code to be exactly the same as the stored procedure.
You will be able to identify the exactly problem using this method.
As mentioned in the comments, it is likely due to the abuse of varchars being converted to numerics.
Summary
Declare and set variables at the top of your sample code so that the rest of the sample is EXACTLY the same as your stored procedure. Then you can start to identify the problem.

Related

using first sql statement result into another sql statement

What basically i want to do is pick all the coordinates from roadData
one by one and then find all the point in tweetMelbourne within 20
miles of it and insert those point into another table.
So for every (x,y) in roadData table find neighbouring data point from
tweetMelbourne and insert those points into another new table.
So I have to do this:
SELECT geo_coordinates_latitude, geo_coordinates_longitude
FROM tweetmelbourne
HAVING ( 3959 * acos( cos( radians(latitude) ) * cos( radians( geo_coordinates_latitude ) ) *
cos( radians( geo_coordinates_longitude ) - radians(longitude) ) + sin( radians(latitude) ) *
sin( radians( geo_coordinates_latitude ) ) ) ) < .1 ORDER BY distance LIMIT 0 , 20;
in which the value of latitude and longitude i have to get from another table :
select longitude,latitude from roadData;
describe tweetmelbourne;
describe roadData;
SELECT geo_coordinates_latitude, geo_coordinates_longitude
FROM tweetmelbourne;
select longitude,latitude from roadData;
The correct syntax of IN() with multiple arguments is : (Val1,Val2) IN(SELECT VAL1,val2..
SELECT t.address,(t.x+t.y) as z
FROM student t
WHERE (t.x,t.y) IN(SELECT x,y FROM tweet)
Also can be done with a join :
SELECT t.address,(t.x+t.y) as z
FROM student t
JOIN tweet s
ON(t.x = s.x and t.y = s.y)
EDIT: I think what you want is:
SELECT s.address,t.x+t.y as z
FROM student s
CROSS JOIN tweet t
Try this:
SELECT s.address, (t.x + t.y) as z
from (SELECT id,x,y FROM `tweet`) as t, student s
WHERE t.id = s.id;
You need to join the two tables, calculating the distance in the ON clause to select the nearby rows.
SELECT *
FROM tweetmelbourne
JOIN roadData
ON ( 3959 * acos( cos( radians(latitude) ) * cos( radians( geo_coordinates_latitude ) ) *
cos( radians( geo_coordinates_longitude ) - radians(longitude) ) + sin( radians(latitude) ) *
sin( radians( geo_coordinates_latitude ) ) ) ) < .1
This will be very slow if the tables are large. It's not possible to use indexes to implement the join, so it will have to perform that complex formula on every pair of rows. You might want to look at MySQL's Spatial Data extensions.

error -1054 unknown column e.id in order clause

I have a query like this -
SELECT e.id FROM event e WHERE e.startdatetime<NOW() AND e.isEventDeleted=FALSE AND e.isNeighborlyInvited=TRUE AND e.organized_by!=49 AND e.event_address IN (SELECT id FROM address a WHERE latitude!='' AND longitude!='' AND IFNULL(( 3959 * ACOS( COS( RADIANS(22.6979425) ) * COS( RADIANS( latitude ) ) * COS( RADIANS( longitude ) - RADIANS(75.8597305) ) + SIN( RADIANS(22.6979425) ) * SIN( RADIANS( latitude ) ))),0)<100) AND e.id NOT IN (SELECT eventid FROM event_interest WHERE approvalStatus!='InterestExpressed' AND interested_user=49) AND e.id NOT IN (SELECT eventid FROM event_invite WHERE invited_user=49 )
UNION
SELECT e.id FROM event e WHERE e.isEventDeleted=FALSE AND e.isNeighborlyInvited=TRUE AND e.organized_by!=49 AND EXISTS (SELECT id FROM address a WHERE latitude!='' AND longitude!='' AND e.event_address=id AND IFNULL(( 3959 * ACOS( COS( RADIANS(22.6979425) ) * COS( RADIANS( latitude ) ) * COS( RADIANS( longitude ) - RADIANS(75.8597305) ) + SIN( RADIANS(22.6979425) ) * SIN( RADIANS( latitude ) ))),0)<100) AND NOT EXISTS (SELECT eventid FROM event_interest WHERE e.id =eventid AND approvalStatus!='InterestExpressed' AND interested_user=49) AND NOT EXISTS (SELECT eventid FROM event_invite WHERE eventid=e.id AND invited_user=49 )
ORDER BY e.id,((SELECT AVG(avgr.abc) AS VALUE FROM ( SELECT YEAR(NOW())-YEAR(dob) AS abc FROM user_detail WHERE userid=(SELECT interested_user FROM event_interest WHERE eventid=477 AND approvalStatus='Approve') UNION SELECT YEAR(NOW())-YEAR(dob) AS abc FROM user_detail WHERE userid=(SELECT invited_user FROM event_invite WHERE eventid=477 AND acceptance='Accept')) AS avgr)+(SELECT IFNULL(( 3959 * ACOS( COS( RADIANS(22.6979425) ) * COS( RADIANS( latitude ) ) * COS( RADIANS( longitude ) - RADIANS(75.8597305) ) + SIN( RADIANS(22.6979425) ) * SIN( RADIANS( latitude ) ))),0) FROM address a WHERE latitude!='' AND longitude!='' AND e.event_address=id));
This one is giving me error 1054 unknown column e.id in order clause.
I was checking on google every where its naming mistake, but i am not getting how it is naming mistake please let me know if i am doing any thing wrong.
Try this by removing the e from ORDER BY clause since you are using the UNION statement:
ORDER BY id
instead of
ORDER BY e.id
Your original question has been answered. e.id is no more available after UNION. Only id is.
However there is some things I would like to add:
If I am not mistaken, the only difference between the first statement and the second is that in the first statement you require e.startdatetime to be less than NOW(). So the first statement retrieves a sub set of what the second statement retrieves. So you can remove the first statement completely including the union clause.
You select only from table event. You order first by id. An id should be unique for a table. So the rest of the order by clause is just void; it won't change the order at all.
In a comment to the first answer you got, you remark that you would like to order by a column, but you dont want to show it in your results. To achieve this do the following:
.
select a, b, c
from
(
select a, b, c, d
... -- complete query here
)
order by d;

MySQL location select query returns 0 in stored procedure

Can anybody spot the problem here?
I have a stored procedure I wanna use to find closest locations to a specific location.
When I try the select outside of a stored proc (just in a query window) all is fine.
SELECT id,
( 3959*acos(
cos(radians(37)) *
cos(radians(lat)) *
cos(radians(lng) - radians(-122)) +
sin(radians(37)) *
sin(radians(lat))
)
) AS distance
FROM markers
HAVING distance < 25
ORDER BY distance
LIMIT 0 , 20;
But when I place it in a stored proc it always return 0.
DELIMITER $$
CREATE PROCEDURE `GetLocationsByRadius`(IN latitude double, IN longitude double,IN radius double)
begin
SELECT ( 6371 * acos( cos( radians(latitude) ) * cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians(longitude ) ) + sin( radians(latitude) ) * sin( radians( Latitude ) ) ) ) AS distance FROM LocationTrades HAVING distance < radius ORDER BY distance LIMIT 0 , 20;
end $$
I tried changing the table data types from float4 to float8 to decimals, I tried using inner variables inside the stored, but nothing helps, it always returns distance 0.
Seems like it thinks something is INT inside there...
Any help would be appreciated.
Thanks
Ok, I found the problem.
The table columns need table identifiers before them. (Table.Column)
This works:
DELIMITER $$
CREATE PROCEDURE GetLocationsByRadius(IN latitude double, IN
longitude double,IN radius double) begin
SELECT ( 6371 * acos( cos( radians(latitude) ) * cos( radians(
Locations.Latitude ) ) * cos( radians( Locations.Longitude ) -
radians(longitude) ) + sin( radians(latitude) ) * sin( radians(
Locations.Latitude ) ) ) ) AS distance FROM Locations HAVING distance
< radius ORDER BY distance LIMIT 0 , 20;
end $$

MySQL logic: different result for Stored Procedure vs Query with just body of Proceduce

Ok so my stored procedure is reading variables wrong in its MySQL query. The results I need are obtained fine when I just use the body of the proc. I would like to make this a stored procedure.
Here is the SP in SQLyog:
DELIMITER $$
USE `XXXXXXXXXXXXXXX`$$
DROP PROCEDURE IF EXISTS `getcusbyzip`$$
CREATE DEFINER=`XXXXXXXXXXXXXXX`#`%` PROCEDURE `getcusbyzip`(IN zipcode VARCHAR(30), IN radius VARCHAR(30))
BEGIN
SELECT C.CustomerName, C.MenuId
FROM Customers C
INNER JOIN (
SELECT ZIPCODE, ( 3959 * ACOS( COS( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) * COS( RADIANS( LAT ) ) * COS( RADIANS( LNG ) - RADIANS( (
SELECT Z.LNG
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) + SIN( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) * SIN( RADIANS( LAT ) ) ) ) AS distance
FROM ZipCodes
HAVING distance <radius
ORDER BY distance
) AS RelevantCodes ON ( C.ZIPCODE = RelevantCodes.ZIPCODE );
END$$
DELIMITER ;
Now there is only 1 record that should be returned because I have only 1 customer added for now until I get this type issue resolved. Here is where I have a breakthrough (please don't laugh, I am new to SQL entirely :) ).
I have tried changing the TYPE as well for the parameters. The zipcode broke after I changed it to an INT and I used this:
CALL getcusbyzip(08361,50)
and my resulting rows were all the rows in which "8361" were in the zipcode. Basically that is my only personal explanation as to why I received so many rows back.
When I use this with both params set to VARCHAR type:
CALL getcusbyzip(08361,50)
or
CALL getcusbyzip('08361',50)
or
CALL getcusbyzip(08361,'50')
you get the point.
I get 0 rows back when I should be getting 1 row back.
So now I think Iknow what my problem is and I might actually ask it hopefully. What is causing my SP to read the input differently as a parameter than as if I just did a query and manually put the parameters into the query. Secondly how can I adjust my procedure so that the MySQL server reads my procedure just like my Query but with the parameters ofcoarse?
Below is the query that works perfectly fine:
SELECT C.CustomerName, C.MenuId
FROM Customers C
INNER JOIN (
SELECT ZIPCODE, ( 3959 * ACOS( COS( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =08360
LIMIT 0 , 1
) ) ) * COS( RADIANS( LAT ) ) * COS( RADIANS( LNG ) - RADIANS( (
SELECT Z.LNG
FROM ZipCodes Z
WHERE Z.ZIPCODE =08360
LIMIT 0 , 1
) ) ) + SIN( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =08360
LIMIT 0 , 1
) ) ) * SIN( RADIANS( LAT ) ) ) ) AS distance
FROM ZipCodes
HAVING distance <50
ORDER BY distance
) AS RelevantCodes ON ( C.ZIPCODE = RelevantCodes.ZIPCODE )
EDIT:
Another point to note is that when I change the variables to direct information in the SP(Stored Procedure) that does not fix it either so it has to be something I missing in MySQL procedure logic. I honestly do not understand why the results are different just because its in a stored procedure.

Declaring and setting variables to test difference between SP and query

I am trying to solve another problem here. I was told by a member that in order to find an answer to my problem I needed to change the query to match the SP. In order to do that I was told to declare variables so I am using variables like I am in the SP. my problem is I have read so much my eyes are hurting and I cannot figure out how to declare friggin variables.
Please help!!
This is what I have read so far:
resource 1,
resource 2,
resource 3, resource 4, resource 5
and I could go on an on. I am literally stuck. I am new to SQL and this is bugging me out. I do not have to use a SP but I would really like to so I can learn the dos and donts and hopefully learn enough to help others.
DECLARE zipcode VARCHAR(30)
DECLARE radius VARCHAR(30)
SET zipcode = 08360
SET radius = 50
SELECT C.CustomerName, C.MenuId
FROM Customers C
INNER JOIN (
SELECT ZIPCODE, ( 3959 * ACOS( COS( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) * COS( RADIANS( LAT ) ) * COS( RADIANS( LNG ) - RADIANS( (
SELECT Z.LNG
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) + SIN( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) * SIN( RADIANS( LAT ) ) ) ) AS distance
FROM ZipCodes
HAVING distance <radius
ORDER BY distance
) AS RelevantCodes ON ( C.ZIPCODE = RelevantCodes.ZIPCODE )
I have tried so many combinations from what I have seen on the internet that I am starting to think its just too late in the night to do anything more. If you take a look at some of the resources I looked at you will see where I saw the difference between with '#' and without.
If you want to create a stored proc, you'll need to use the proper syntax.
See: http://dev.mysql.com/doc/refman/5.5/en/create-procedure.html
Note that inside the proc body you'll need to terminate each and every statement with a ;.
Because you'll need to let MySQL know when the body proc ends and you'll need to redeclare the delimiter into something that not a ;.
This will prevent MySQL from interpreting your stored proc after the first ';', but instead listen all the way up to the $$.
Don't forget to revert the delimiter back to the default after you're done inputting the function.
SET DELIMITER $$
CREATE PROCEDURE QueryCustomerMenu(IN zipcode VARCHAR(30), IN radius VARCHAR(30))
BEGIN
DECLARE somevar VARCHAR(20);
SET somevar = '456';
SELECT C.CustomerName, C.MenuId
FROM Customers C
INNER JOIN (
SELECT ZIPCODE, ( 3959 * ACOS( COS( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) * COS( RADIANS( LAT ) ) * COS( RADIANS( LNG ) - RADIANS( (
SELECT Z.LNG
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) + SIN( RADIANS( (
SELECT Z.LAT
FROM ZipCodes Z
WHERE Z.ZIPCODE =zipcode
LIMIT 0 , 1
) ) ) * SIN( RADIANS( LAT ) ) ) ) AS distance
FROM ZipCodes
HAVING distance <radius
ORDER BY distance
) AS RelevantCodes ON ( C.ZIPCODE = RelevantCodes.ZIPCODE );
END $$
SET DELIMITER ;
Now you can call the stored proc with:
CALL QueryCustomerMenu('09210','20');
And it will return a resultset with the CustomerName and MenuID's.