MYSQL Insert into select filtering fields - mysql

I have to insert a new row in table1 for each row found in table2.
The problem is that the select in table2 returns more fields than are needed to the insert, but are useful in where clause of select.
This query shows to a user all the shops around, based on their (shops) range (defined in the table stores)
SELECT destination.poi_id,
6371 *
2 *
ASIN(
SQRT(
POWER(SIN((use_lat - poi_lat) * PI()/180 / 2), 2) +
COS(use_lat * pi()/180) *
COS(poi_lat * pi()/180) *
POWER(SIN((use_lon - poi_lon) * PI()/180 / 2), 2)
)
) AS distance,
destination.poi_range AS range
FROM stores destination, users origin
WHERE origin.use_id=userid
AND destination.poi_lon BETWEEN lon1 AND lon2
AND destination.poi_lat BETWEEN lat1 AND lat2
HAVING distance <= range
ORDER BY distance;
Now I have to put these results in a table having this structure
user_id INTEGER
poi_id INTEGER
ins_date TIMESTAMP (CURRENT TIMESTAMP)
I don't know how to do it, can you help me?
INSERT INTO table (user_id, poi_id)
SELECT ... ? (too many fields in select)

Reading between the lines a bit but basically only include the columns you need in the insert IE:
INSERT INTO table (user_id, poi_id)
SELECT use_id,poi_id,NOW() FROM
(SELECT origin.use_id,destination.poi_id,6371 *
2 *
ASIN(
SQRT(
POWER(SIN((use_lat - poi_lat) * PI()/180 / 2), 2) +
COS(use_lat * pi()/180) *
COS(poi_lat * pi()/180) *
POWER(SIN((use_lon - poi_lon) * PI()/180 / 2), 2)
)
) as distance
FROM stores destination, users origin
WHERE origin.use_id=userid
AND destination.poi_lon BETWEEN lon1 AND lon2
AND destination.poi_lat BETWEEN lat1 AND lat2
HAVING distance <= range) sub1
ORDER BY distance;

You just need to add in your select user_id and remove distance and range because there are not in your table and actually you have to add ins_date because you dont define VALUE statement in your Insert. So your Select should be something like this
INSERT INTO table values (user_id, poi_id)
Select user_id, poi_id from FROM stores destination, users origin
WHERE origin.use_id=userid
AND destination.poi_lon BETWEEN lon1 AND lon2
AND destination.poi_lat BETWEEN lat1 AND lat2
HAVING distance <= range
ORDER BY distance;
if you need to add date in your table include this field within brackets and into select statement too

Related

Calculate the distance(km) between two latitude and longitude using MySQL

this is Lat and Lon example in mysql database
ID | Lat | Lon
1 | 3.1412 | 101.6865
2 | 1.2897 | 103.8501
The formula below calculates the distance between two Lat (latitudes) and Lon (longitudes) and gets the result that I want. But this formula doesn't extract my Lat and Lon from the database. I would like to ask, how to get the distance result by using ID and calculate two Lat and Lon? My friend told me using Join table, but I still don't get the answer..
SELECT ROUND(6353 * 2 * ASIN(SQRT( POWER(SIN((3.1412 -
abs(1.2897)) * pi()/180 / 2),2) + COS(3.1412 * pi()/180 ) * COS(
abs(1.2897) * pi()/180) * POWER(SIN((101.6865 - 103.8501) * pi()/180 / 2), 2) )), 2);
Thanks for advance
You can join the same table two time one for Id 1 and one for id 2 assigning different alias name
then use the related column name
SELECT ROUND(6353 * 2 * ASIN(SQRT( POWER(SIN((a.lat -
abs(b.lat)) * pi()/180 / 2),2) + COS(a.lat * pi()/180 ) * COS(
abs(b.lat) * pi()/180) * POWER(SIN((a.lng - b.lng) * pi()/180 / 2), 2) )), 2);
from my_table a
inner join my_table b on a.id = 1 and b.id = 2
It is working for me
SELECT *,(((acos(sin((12.942999*pi()/180)) * sin((`Lat`*pi()/180))+cos((12.942999*pi()/180)) * cos((`Lat`*pi()/180)) * cos(((74.82994- `Lon`)* pi()/180))))*180/pi())*60*1.1515*1.609344 ) as distance FROM ven_vendor HAVING distance <= 10

How to search for events in 5 km radius

I'm trying to select events in a 5 km radius and order them by likes and from oldest to newest. I know how to select events and order them by likes, but I can't figure this one out. The problem maybe is that the location is stored in a different table.
Database structure:
event plusone (like) location
id_event id_plusone id_location
location_id event_id lat
... user_id lon
... city_id
full_name
....
The SQL statement I'm trying:
SELECT 3956 * 2 * ASIN(
SQRT(POWER(SIN((50.127946 - abs(l.lat)) * pi()/180 / 2),2) + COS(50.127946 * pi()/180 ) *
COS(abs(l.lat) * pi()/180) * POWER(SIN((14.4882912 - l.lon) * pi()/180 / 2), 2) )) AS distance,e.*,COUNT( p.id_plusone ) AS
likes
FROM
event e,location l
LEFT JOIN plusone p ON p.event_id = e.id_event
WHERE
e.location_id = l.id_location AND distance<=5 GROUP BY e.id_event
ORDER BY e.timestamp DESC,likes DESC
The huge column at the beginning is calculation of distance of the event from user position using latitude and longitude.
This is what I get from the SQL debugger:
#1054 - Unknown column 'distance' in 'where clause'
Does anybody know how to do this?
Is hard to track where the error is, you should try to solve the distance part first.
SELECT
event_id,
3956 * 2 * ASIN(SQRT( POWER(SIN((50.127946 - abs(l.lat)) * pi()/180 / 2),2)
+ COS(50.127946 * pi()/180 ) * COS(abs(l.lat) * pi()/180) * POWER(SIN((14.4882912 – l.lon) * pi()/180 / 2), 2) )) AS distance,
FROM event e
JOIN location l
WHERE distance <= 5
And then join to back to the event table
SELECT e.*, count(p.id_plusone)
FROM event e
LEFT JOIN plusone p
ON p.event_id = e.id_event
JOIN ( Previous Distance Query) d
ON e.event_id = d.event_id
GROUP BY e.id_event
ORDER BY e.timestamp DESC, likes DESC
and btw, this group_by will bring you event_id plus random values for e.* so be carefull
$latitudeD= latitude;
$longitudeD = longitude;
SELECT event,
SQRT(
POW(69.1 * (coordX - $latitudeD), 2) +
POW(69.1 * ($longitudeD - coordY) * COS(coordX / 57.3), 2)) AS distance
FROM db.table WHERE SQRT(
POW(69.1 * (coordX - $latitudeD), 2) +
POW(69.1 * ($longitudeD - coordY) * COS(coordX / 57.3), 2)) < 50 ORDER BY distance
;

MySQL using `IN` while having multiple values

I am trying to count of coupons sold by each store from the list of stores within 20 miles range. I know the following syntax will work if there is only 1 store.
SELECT sum(couponscount) as count where restaurant IN (SELECT storename where bhal bhal bhal and output is one value)
What is I the IN (SELECTstorenamewhere bhal bhal bhal and output is multiple values) will return multiple values?
Like in my case the complete SQL is like and its not working
SELECT sum(couponscount) as count FROM `coupons` having `restaurant` IN (SELECT `storename`, ((ACOS(SIN(-27.561264299999998 * PI()/180) * SIN(latitude * PI()/180) + COS(-27.561264299999998 * PI()/180) * COS(latitude * PI()/180) * COS((153.07304890000003 – longitude) * PI()/180)) *180 / PI( )) *60 * 1.1515) AS `distance` FROM `stores` WHERE `status`=’active’ HAVING `distance` <=20)
Is there anyway to make it working?
SELECT sum(couponscount) AS COUNT,restaurant
FROM `coupons`
WHERE `restaurant` IN
(SELECT `storename`
FROM `stores`
WHERE `status`='active'
AND
((ACOS(SIN(-27.561264299999998 * PI()/180) * SIN(latitude * PI()/180) + COS(-27.561264299999998 * PI()/180) * COS(latitude * PI()/180) * COS((153.07304890000003 – longitude) * PI()/180)) *180 / PI()) *60 * 1.1515) <=20)
GROUP BY restaurant
Also use proper quotes for active.
Presumably, you want to get the count of coupons from stores within a distance of 20. Moving the having condition to a where clause should do what you want:
SELECT sum(couponscount) as count
FROM `coupons`
WHERE `restaurant` IN (SELECT `storename`
FROM `stores`
WHERE `status` = 'active' AND
((ACOS(SIN(-27.561264299999998 * PI()/180) * SIN(latitude * PI()/180) + COS(-27.561264299999998 * PI()/180) * COS(latitude * PI()/180) * COS((153.07304890000003 – longitude) * PI()/180)) *180 / PI( )) *60 * 1.1515) <= 20
);
You had a major syntax problem because your subquery returned two columns. When you use a subquery with in, you can only return one column, in this case, storename. I moved the code for the distance calculation to the where clause. No having clause is needed either in the subquery or the outer query.

Zipcode Radius Search with POINT Column

I have a MySQL Routine that is getting records within a 50 mile radius when passed Latitude and Longitude via utilizing the Haversin equation.
While this works great, and is pretty speedy (considering it's searching through 82k records), I am thinking that I can get better performance by creating a similar procedure utilizing a POINT column.
So, in my table I created an extra column called Location, gave it a datatype of POINT, updated my data to pass lat & lon to the Location column. Data is valid, and is fine., and added a Spatial Index
The question is, how can I convert the following query to use the Location column, instead of lat and lon columns.
SET #LAT := '37.953';
SET #LON := '-105.688';
SELECT DISTINCT
BPZ.`store_id`,
3956 * 2 * ASIN(SQRT(POWER(SIN((#LAT - abs(Z.`lat`)) * pi()/180 / 2),2) + COS(#LAT * pi()/180 ) * COS(abs(Z.`lat`) * pi()/180) * POWER(SIN((#LON - Z.`lon`) * pi()/180 / 2), 2))) as distance,
c.`name`,c.`address`,c.`city`,c.`state`,c.`phone`,c.`zip`,c.`premise_type`
FROM
`zip_codes` as Z,
`brand_product_zip` as BPZ
LEFT JOIN `customers` c ON c.`store_id` = BPZ.`store_id`
WHERE
BPZ.`zip` = Z.`zip`
AND
3956 * 2 * ASIN(SQRT(POWER(SIN((#LAT - abs(Z.`lat`)) * pi()/180 / 2),2) + COS(#LAT * pi()/180 ) * COS(abs(Z.`lat`) * pi()/180) * POWER(SIN((#LON - Z.`lon`) * pi()/180 / 2), 2))) <= 50
ORDER BY
distance LIMIT 20
I understand that this has been asked before, however, everything I see points to calculations based on lat and lon and not the POINT column
Updated Code:
SET #lat = 41.92;
SET #lon = -72.65;
SET #kmRange = 80.4672; -- = 50 Miles
SELECT *, (3956 * 2 * ASIN(SQRT(POWER(SIN((#lat - abs(`lat`)) * pi()/180 / 2),2) + COS(#lat * pi()/180 ) * COS(abs(`lat`) * pi()/180) * POWER(SIN((lon - `lon`) * pi()/180 / 2), 2)))) as distance
FROM `zip_codes`
WHERE MBRContains(LineString(Point(#lat + #kmRange / 111.1, #lon + #kmRange / (111.1 / COS(RADIANS(#lat)))), Point(#lat - #kmRange / 111.1, #lon - #kmRange / (111.1 / COS(RADIANS(#lat))))), `Location`)
Order By distance
LIMIT 20
Have you looked into hilbert curves solutions? A spatial index doesn't deliver the exact solution? . With a mysql spatial index you can use mbrcontains:
CREATE TABLE lastcrawl (id INT NOT NULL PRIMARY KEY, pnt POINT NOT NULL) ENGINE=MyISAM;
INSERT
INTO lastcrawl
VALUES (1, POINT(40, -100));
SET #lat = 40;
SET #lon = -100;
SELECT *
FROM lastcrawl
WHERE MBRContains
(
LineString
(
Point
(
#lat + 10 / 111.1,
#lon + 10 / ( 111.1 / COS(RADIANS(#lat)))
),
Point (
#lat - 10 / 111.1,
#lon - 10 / ( 111.1 / COS(RADIANS(#lat)))
)
),
pnt
);
Look here: MySQL - selecting near a spatial point.
Here: http://www.drdobbs.com/database/space-filling-curves-in-geospatial-appli/184410998
The article Nearest-location finder for MySQL explains in detail various options, and the best choice for use with the Spatial Extensions starting with MySQL 5.6.
From the article, this sample query lists zip codes within a 50 mile radius from given coordinates (42.81, -70.81):
SELECT zip, primary_city,
latitude, longitude, distance_in_mi
FROM (
SELECT zip, primary_city, latitude, longitude,r,
69.0 * DEGREES(ACOS(COS(RADIANS(latpoint))
* COS(RADIANS(latitude))
* COS(RADIANS(longpoint) - RADIANS(longitude))
+ SIN(RADIANS(latpoint))
* SIN(RADIANS(latitude)))) AS distance_in_mi
FROM zip
JOIN (
SELECT 42.81 AS latpoint, -70.81 AS longpoint, 50.0 AS r
) AS p
WHERE latitude
BETWEEN latpoint - (r / 69)
AND latpoint + (r / 69)
AND longitude
BETWEEN longpoint - (r / (69 * COS(RADIANS(latpoint))))
AND longpoint + (r / (69 * COS(RADIANS(latpoint))))
) d
WHERE distance_in_mi <= r
ORDER BY distance_in_mi;

How to lookup nearest location (Latitude / Longitude) in a join query

I have a table with a list of users, which looks something like;
Users.. ( id, username, lat, long )
I have a location table which looks like this:
Locations.. ( id, name, lat, lng, bound_ne_lat, bound_ne_lng, bound_sw_lat, bound_sw_lng
What I'm trying to do, is something like;
SELECT Users.*, Locations.name as NearestTown
FROM Users
INNER JOIN Locations ON ( .. lookup nearest town from Locations based on Users lat lng coords, return only the nearest result .. )
I did think about doing some kind of subquery, like;
INNER JOIN Locatios ON Locations.id IN (SELECT id FROM Locations ORDER BY (..distance query) desc limit 1
But then I found out I couldn't pass the users lat / lng into to the sub query for each result.
The current formula I do use however to calculate the distance between the 2 points is;
(3956 * 2 * ASIN(SQRT( POWER(SIN((#sourceLat - table.lookupLat) * pi()/180 / 2), 2) +COS(#sourceLat * pi()/180) * COS(table.lookupLat * pi()/180) * POWER(SIN((#sourceLng - table.lookupLng) * pi()/180 / 2), 2) ))) as Distance,
However, how could I use this in a subquery [if the best option] when I cannot pass in the #sourceLat and #sourceLng for each result .. ?
Any help, most appreciated.