Am trying to select all items from item_table
based on user distance from the seller stores. Below code actually work fine till i use FIND_IN_SET
to allow showing one product in two or more different location if the location loc_id
is in array of item item_loc_ids
.
What i actually want to archive is to show one product to users from different locations provided the store coordinate is within the user location and the location ID
is in list of locations where the item should be available based on distance calculation.
seller_table
seller_name | seller_id
-----------------|-----------------
Peter | PP1
John | JJ6
location_table
loc_name | loc_id | loc_lat | loc_lng | seller_id
-----------|----------|-----------|-------------|----------
Office 1 | 1A | 2.908810 | 101.651398 | PP1
Office 2 | 1B | 3.051953 | 101.671417 | PP1
Outlet S | 3A | 3.051953 | 101.671455 | JJ6
Item_table
item_name | item_id | item_loc_ids | item_seller
-----------|----------|----------------|------------------
Java | 1 | 1A, 1B | PP1
PHP | 2 | 1A | PP1
CSS | 3 | 1B | PP1
SQL | 4 | 1B, 1A | PP1
Python | 5 | 3A | JJ6
User Data
$userLatitude = 2.908810;
$userLongitude = 101.651398;
$userDistance = 5.5;
Query
SELECT seller.*,loc.*, item.*, 3956 * 2 * ASIN(SQRT(POWER(SIN((loc.loc_lat - ABS($userLatitude)) * PI()/180 / 2), 2) + COS(loc.loc_lng * PI()/180 ) * COS(ABS( $userLatitude) * PI()/180) * POWER(SIN((loc.loc_lng - $userLongitude) * PI()/180 / 2), 2))) AS distance
FROM (
SELECT item.*,
ROW_NUMBER() OVER(PARTITION BY Item.item_seller ORDER BY Item.item_seller) AS limit_group
FROM Item_table Item
) p
INNER JOIN seller_name seller
ON Item.item_seller = seller.seller_id
INNER JOIN location_table loc
ON FIND_IN_SET(loc.loc_id, Item.item_loc_ids)
WHERE limit_group <= 5
HAVING distance <= $userDistance
OR distance IS NULL
ORDER BY distance IS NULL DESC, distance DESC
LIMIT 100
The above code work only on one location_id, but if more it won't return any record.
I added a link to sql fiddle http://sqlfiddle.com/#!9/8c085b/4
and DDLs of same:
CREATE TABLE `location_table` (
`loc_name` VARCHAR(50) NULL DEFAULT NULL,
`loc_id` VARCHAR(50) NULL DEFAULT NULL,
`loc_lat` VARCHAR(500) NULL DEFAULT NULL,
`loc_lng` VARCHAR(500) NULL DEFAULT NULL,
`seller_id` VARCHAR(500) NULL DEFAULT NULL
);
INSERT INTO `location_table` (`loc_name`, `loc_id`, `loc_lat`, `loc_lng`, `seller_id`)
VALUES ('Office 1', '1A', '2.908810', '101.651398', 'PP1'),
('Office 1', '1B', '3.051953', '101.671417', 'PP1'),
('Outlet S', '3A', '3.051953', '101.671455', 'JJ6');
CREATE TABLE `seller_table` (
`seller_name` VARCHAR(50) NULL DEFAULT NULL,
`seller_id` VARCHAR(50) NULL DEFAULT NULL
);
INSERT INTO `seller_table` (`seller_name`, `seller_id`) VALUES ('Peter', 'PP1'), ('John', 'JJ6');
CREATE TABLE `item_table` (
`item_name` VARCHAR(50) NULL DEFAULT NULL,
`item_id` VARCHAR(50) NULL DEFAULT NULL,
`item_store_ids` VARCHAR(100) NULL DEFAULT NULL,
`item_seller` VARCHAR(50) NULL DEFAULT NULL
);
INSERT INTO `item_table` (`item_name`, `item_id`, `item_store_ids`, `item_seller`) VALUES ('Java', '1', '1A, 1B ', 'PP1'),
('PHP', '2', '1A ', 'PP1'),
('CSS', '3', '1B ', 'PP1'),
('SQL', '4', '1B, 1A ', 'PP1'),
('Python', '5', '3A ', 'JJ6');
SELECT seller.*,loc.*, item.*, 3956 * 2 * ASIN(SQRT(POWER(SIN((loc.loc_lat - ABS(2.908810)) * PI()/180 / 2), 2) + COS(loc.loc_lng * PI()/180 ) * COS(ABS(2.908810) * PI()/180) * POWER(SIN((loc.loc_lng - 101.651398) * PI()/180 / 2), 2))) AS distance
FROM (
SELECT item.*,
ROW_NUMBER() OVER(PARTITION BY item.item_seller ORDER BY item.item_seller) AS limit_group
FROM item_table item
) p
INNER JOIN seller_table seller
ON item.item_seller = seller.seller_id
INNER JOIN location_table loc
ON FIND_IN_SET(loc.loc_id, item.item_store_ids)
WHERE limit_group <= 5
HAVING distance <= 5.5
OR distance IS NULL
ORDER BY distance IS NULL DESC, distance DESC
LIMIT 100