Different calculation figure in arithmetic TSQL - sql-server-2008

I am getting diff. figures in my below equation written.
SELECT 9.36 + 9.36 / ( 284.36 ) * 15.64 = 9.8748065528 (CORRECT)
SELECT 18.72 / ( 284.36 ) * 15.64 = 1.0296131056 (INCORRECT)
I have total (9.36 * 2) Which I am putting in second select statement and gives incorrect amount.
What I am doing wrong?

The equations are not the same.
The second statement is the equivalent of:
SELECT (9.36 + 9.36) / ( 284.36 ) * 15.64
not
SELECT 9.36 + 9.36 / ( 284.36 ) * 15.64
Remember your Order of Operations.

THIS is what I want.
SELECT 9.36 + (9.36 / ( 284.36 ) * 15.64)

Related

How can I run subqueries in mysql

I am trying to run subqueries from another table in a query
My Query is as follows:
SELECT *, (6371000 * acos(cos(radians(select point_oi.lng
from point_oi
where point_oi.name like '%Main Square%')
)
* cos(radians(restaurants.lat)) * cos(radians(restaurants.lng)
- radians(select point_oi.lng
from point_oi
where point_oi.name like '%Main Square%'
))
+ sin(radians(select point_oi.lng
from point_oi
where point_oi.name like '%Main Square%'))
* sin(radians(restaurants.lat)))) AS distance
FROM restaurants
HAVING distance < 500;
When I run the Query I get an error saying that there is an error near select.
I would like to use the nested select queries to get the lat and lng from another table rather than hardcoding the values.
How can I fix this.
Thank you for your help
You should not use subquery for retrieve point_poi lat, lnt if the suquery return more than a rows you have error ..
try use a proper join (in this case do the fatc you have not relation between point_poi and restaurants you could use cross join )
SELECT restaurants.*,
(6371000 * acos(cos(radians(point_oi.lng ))
* cos(radians(restaurants.lat)) * cos(radians(restaurants.lng)
- radians(point_oi.lng ))
+ sin(radians(point_oi.lng ))
* sin(radians(restaurants.lat)))) AS distance
FROM restaurants
CROSS JOIN point_oi
WHERE point_oi.name like '%Main Square%'
AND (6371000 * acos(cos(radians(point_oi.lng ))
* cos(radians(restaurants.lat)) * cos(radians(restaurants.lng)
- radians(point_oi.lng ))
+ sin(radians(point_oi.lng ))
* sin(radians(restaurants.lat)))) < 500;
Please try this query and let me know is your issue resolve.
SELECT t.*
,(6371000 * acos(cos(radians(SELECT point_oi.lng FROM point_oi WHERE point_oi.name LIKE '%Main Square%')) * cos(radians(restaurants.lat)) * cos(radians(restaurants.lng) - radians(SELECT point_oi.lng FROM point_oi WHERE point_oi.name LIKE '%Main Square%')) + sin(radians(SELECT point_oi.lng FROM point_oi WHERE point_oi.name LIKE '%Main Square%')) * sin(radians(restaurants.lat)))) AS distance
FROM restaurants As t
WHERE distance < 500;

SELECT *, sum() with equation only returns one row

SELECT *,
(SUM(`q6`) /
(`q1` *
(`q1` + `q2` + `q3` + `q4` + `q5` + `q6`) / 6)
* 100) AS percent
FROM table
WHERE field2 = 'xxx'
ORDER BY `percent` ASC
The code above is returning me the correct value for "percent" but only returns one row. I need it to return all the rows, 15 of them.
In my equation I am trying to get the value "percent" for each row and ORDER by the highest percent.
It seems, as soon as I add the sum() to my select statement, that it then returns only one row.
Assuming all comments, you should get something like:
SELECT
*, (SUM(`q6`) / (`q1` * (`q1` + `q2` + `q3` + `q4` + `q5` + `q6`) / 6) * 100)
AS percent
FROM table
WHERE field2 = 'xxx'
GROUP BY id ORDER BY `percent` DESC
In MySQL you can include columns in the select that are not aggregated and not in the group by. Because your query has an aggregation function, MySQL recognizes it as an aggregation query, and only returns one row.
Actually, you need to bring in the total value for a calculation on each row. Here is one way using a subquery in the select statement:
SELECT *,
(select sum(q6) as sumq6 from table where field2 = 'xxx') / (`q1` * (`q1` + `q2` + `q3` + `q4` + `q5` + `q6`) / 6)
* 100) AS percent
FROM table
WHERE field2 = 'xxx'
ORDER BY `percent` ASC;
Here is another way, using a cross join:
SELECT *,
(sumq6 / (`q1` * (`q1` + `q2` + `q3` + `q4` + `q5` + `q6`) / 6)
FROM table cross join
(select sum(q6) as sumq6 from table where field2 = 'xxx') as const
WHERE field2 = 'xxx'
ORDER BY `percent` ASC;

Slow location based search result query

I have a query that I use to find results that are ordered by location. Results also have to account for VAT so this is also in the query. The query can unfortunately take 4+ seconds to run when not cached. Can anyone spot any glaringly obvious issues or suggest anything I can do to improve it?
Just to clarify what is happening in the query:
The distance is calculation is euclidean distance using lat/long
The incvat fields are used to show the price when vat is included
The WHEN / THEN statement is used to put prices of 0 at the very bottom
The query:
SELECT * , ROUND( SQRT( POW( ( 69.1 * ( company_branch_lat - 52.4862 ) ) , 2 ) + POW( ( 53 * ( company_branch_lng - - 1.8905 ) ) , 2 ) ) , 1 ) AS distance,
hire_car_day + ( hire_car_day * 0.2 * ! hire_car_incvat ) AS hire_car_day_incvat,
hire_car_addday + ( hire_car_addday * 0.2 * ! hire_car_incvat ) AS hire_car_addday_incvat,
hire_car_week + ( hire_car_week * 0.2 * ! hire_car_incvat ) AS hire_car_week_incvat,
hire_car_weekend + ( hire_car_weekend * 0.2 * ! hire_car_incvat ) AS hire_car_weekend_incvat
FROM hire_car
LEFT JOIN company_branch ON company_branch_id = hire_car_branchid
LEFT JOIN hire_cartypelink ON hire_cartypelink_carhireid = hire_car_id
LEFT JOIN users ON company_branch_userid = user_id
WHERE 1
GROUP BY hire_car_id
HAVING distance <=30
ORDER BY CASE hire_car_day_incvat
WHEN 0
THEN 40000
ELSE hire_car_day_incvat
END , distance ASC
LIMIT 0 , 30
You can use the mysql spatial extension and save the latitude and longitude as a point datatype and make it a spatial index. That way you can reorder the coordinates along a curve and reduce the dimension and preserve spatial information. You can use the spatial index as a bounding box to filter the query and then use the harvesine formula to pick the optimal result. Your bounding box should be bigger then the radius of the great circle. Mysql uses a rtree with some spatial index and my example was about a z curve or a hilbert curve: https://softwareengineering.stackexchange.com/questions/113256/what-is-the-difference-between-btree-and-rtree-indexing.
Then you can insert a geocoordinate directly into a point column: http://dev.mysql.com/doc/refman/5.0/en/creating-spatial-values.html. Or you can use a geometry datatype: http://markmaunder.com/2009/10/10/mysql-gis-extensions-quick-start/. Then you can use MBRcontains function like so: http://dev.mysql.com/doc/refman/4.1/en/relations-on-geometry-mbr.html or any other functions: http://dev.mysql.com/doc/refman/5.5/en/functions-for-testing-spatial-relations-between-geometric-objects.html. Hence you need a bounding box.
Here are some examples:
Storing Lat Lng values in MySQL using Spatial Point Type
https://gis.stackexchange.com/questions/28333/how-to-speed-up-this-simple-mysql-points-in-the-box-query
Here is a simple example with point datatype:
CREATE SPATIAL INDEX sx_place_location ON place (location)
SELECT * FROM mytable
WHERE MBRContains
(
LineString
(
Point($x - $radius, $y - $radius),
Point($x + $radius, $y + $radius)
)
location
)
AND Distance(Point($x, $y), location) <= $radius
MySQL latitude and Longitude table setup.
I'm not sure if it works because it's uses a radius variable with a bounding-box function. It's seems to me MBRwithin is a bit simpler, because it doesn't need any argument: Mysql: Optimizing finding super node in nested set tree.
You are using GROUP BY statement together with HAVING, although I don't see anywhere in the query any aggregate functions. I recommend you to re-write the query like this and see if it makes any difference
SELECT * , ROUND( SQRT( POW( ( 69.1 * ( company_branch_lat - 52.4862 ) ) , 2 ) + POW( ( 53 * ( company_branch_lng - - 1.8905 ) ) , 2 ) ) , 1 ) AS distance,
hire_car_day + ( hire_car_day * 0.2 * ! hire_car_incvat ) AS hire_car_day_incvat,
hire_car_addday + ( hire_car_addday * 0.2 * ! hire_car_incvat ) AS hire_car_addday_incvat,
hire_car_week + ( hire_car_week * 0.2 * ! hire_car_incvat ) AS hire_car_week_incvat,
hire_car_weekend + ( hire_car_weekend * 0.2 * ! hire_car_incvat ) AS hire_car_weekend_incvat
FROM hire_car
LEFT JOIN company_branch ON company_branch_id = hire_car_branchid
LEFT JOIN hire_cartypelink ON hire_cartypelink_carhireid = hire_car_id
LEFT JOIN users ON company_branch_userid = user_id
WHERE ROUND( SQRT( POW( ( 69.1 * ( company_branch_lat - 52.4862 ) ) , 2 ) + POW( ( 53 * ( company_branch_lng - - 1.8905 ) ) , 2 ) ) , 1 ) <= 30
ORDER BY CASE hire_car_day_incvat
WHEN 0
THEN 40000
ELSE hire_car_day_incvat
END , distance ASC
LIMIT 0 , 30

COUNT(*) and Having

The following query gets me a column of distances.
But what i need is only the count of results with matching distances, not the distances themselves. A Subselect cannot be used.
SELECT
( 6368 * SQRT(2*(1-cos(RADIANS(loc_lat)) * cos(0.899945742869) * (sin(RADIANS(`loc_lon`)) * sin(0.14286767838) + cos(RADIANS(`loc_lon`)) * cos(0.14286767838)) - sin(RADIANS(loc_lat)) * sin(0.899945742869))) ) AS Distance
FROM ...
WHERE ...
HAVING Distance > 0 AND Distance <= 25
You just need to move the distance calculation to the where clause:
SELECT COUNT(*) FROM ...
WHERE ( 6368 * SQRT(2*(1-...) BETWEEN 0 AND 25
If you don't need the distances, only the count, maybe this will work:
SELECT Count(*)
FROM ...
WHERE ... AND
(6368 * SQRT(2*(1-cos(RADIANS(loc_lat)) * cos(0.899945742869) *
(sin(RADIANS(`loc_lon`)) * sin(0.14286767838) + cos(RADIANS(`loc_lon`)) *
cos(0.14286767838)) - sin(RADIANS(loc_lat)) * sin(0.899945742869)))
) BETWEEN 0 AND 25
This will give the totalResults, and you can discard the other column.
SELECT COUNT(*) totalResults,
( 6368 * SQRT(2*(1-cos(RADIANS(loc_lat)) * cos(0.899945742869) * (sin(RADIANS(`loc_lon`)) * sin(0.14286767838) + cos(RADIANS(`loc_lon`)) * cos(0.14286767838)) - sin(RADIANS(loc_lat)) * sin(0.899945742869))) ) AS Distance
FROM ...
WHERE ...
HAVING Distance > 0 AND Distance <= 25

How to get mysql random integer range?

I am trying to generate a random integer for each row I select between 1 and 60 as timer.
SELECT downloads.date, products.*, (FLOOR(1 + RAND() * 60)) AS timer
I have searched and keep coming up to this FLOOR function as how to select a random integer in a range. This is giving me a 1 for every row.
What am I missing?
I am on mysql 5.0.75
Heres the rest of the query I belive it might be a nesting issue
SELECT *
FROM (
SELECT downloads.date, products.*, FLOOR(1 + (RAND() * 60)) AS randomtimer,
(
SELECT COUNT( * )
FROM distros
WHERE distros.product_id = products.product_id
) AS distro_count,
(SELECT COUNT(*) FROM downloads WHERE downloads.product_id = products.product_id) AS true_downloads
FROM downloads
INNER JOIN products ON downloads.product_id = downloads.product_id
) AS count_table
WHERE count_table.distro_count > 0
AND count_table.active = 1
ORDER BY count_table.randomtimer , count_table.date DESC LIMIT 10
This is working for me. Your mysql version maybe?
SELECT id, (FLOOR( 1 + RAND( ) *60 )) AS timer
FROM users
LIMIT 0 , 30
The output of the RAND function will always be a value between 0 and 1.
Try this:
SELECT downloads.date, products.*, (CAST(RAND() * 60 AS UNSIGNED) + 1) AS timer
Old question, but always actual problem.
Here a way to create a MySQL function random_integer() based on manual :
CREATE FUNCTION random_integer(value_minimum INT, value_maximum INT)
RETURNS INT
COMMENT 'Gets a random integer between value_minimum and value_maximum, bounds included'
RETURN FLOOR(value_minimum + RAND() * (value_maximum - value_minimum + 1));
SELECT ALL random_integer(1, 60) AS timer;
I'm running your query and it does give me a random number for each row.... maybe has something to do with the name of the random (timer)?
You can increase the number multiplied by the number of records in the table.
SELECT id,
(FLOOR( (SELECT MIN(id) FROM your_table ) + RAND( ) * 1000000 ) ) AS timer
FROM your_table
LIMIT 0 , 30