我有2张桌子。我的其中一张表users是:
users
id name longitude latitutde ----- ----- ----------- ----------- 1 Mark -76.316528 40.036027 2 John -95.995102 41.25716 3 Paul -82.337036 29.645095 4 Dave -82.337036 29.645095 5 Chris -76.316528 40.036027
我正在使用SQL检测附近的人:SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-122) ) + sin( radians(37) ) * sin(radians(latitude)) ) ) AS distance FROM用户HAVING distance < 50 ORDER BY distance DESC LIMIT 20
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-122) ) + sin( radians(37) ) * sin(radians(latitude)) ) ) AS distance FROM
HAVING distance < 50 ORDER BY distance DESC LIMIT 20
另一个matches是这样的:
matches
id sender receiver status ----- ----- ----------- -----------
发送者是发送邀请者的人,接收者是接收者的人。
SQL请求应在users人员附近搜索并检查matchesID。如果没有作为发送者和接收者的ID,则返回此人的用户ID以建立新的连接。
例如,保罗在寻找附近的人,而戴夫users则在他附近寻找。因此,仅当Dave ID不在matches表中或Paul == receiverAND status == 0时,才应将Dave ID返回给Paul 。
receiver
如何编写此SQL查询以返回附近人员的20个ID?
我将距离公式更改为自mysql 5.7起可用的格式。您没有_指定您的数据库或提供了一个小提琴示例来展示您的系统,因此我选择5.7作为mini9mum,它也可以在8.0中使用,就像您在小提琴中看到的那样。
内部查询需要两件事:搜索的用户ID和他的位置,因为从结果中排除了他,并且当然要计算距离。
查询的结果在where子句中检查-我希望我有正确的主意,因此您应该检查一下
CREATE TABLE users (`id` varchar(5), `name` varchar(5), `longitude` varchar(11), latitude varchar(11)) ; INSERT INTO users (`id`, `name`, `longitude`, `latitude`) VALUES ('1', 'Mark', '-76.316528', '40.036027'), ('2', 'John', '-95.995102', '41.25716'), ('3', 'Paul', '-82.337036', '29.645095'), ('4', 'Dave', '-82.337036', '29.645095'), ('5', 'Chris', '-76.316528', '40.036027'), ('6', 'Manny', '-82.338036', '29.645095'), ('7', 'Fred', '-82.338036', '29.646095') ; ✓ ✓ CREATE TABLE matches (`id` int, `sender` int, `receiver` int, `status` int) ; INSERT INTO matches (`id`, `sender`, `receiver`, `status`) VALUES (1, 3, 4, 0), (2, 1, 5, 1), (3, 6, 3, 1) ; ✓ ✓ SELECT id , ( 3959 * acos( cos( radians(37) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-122) ) + sin( radians(37) ) * sin(radians(latitude)) ) ) AS distance FROM users HAVING distance < 50 ORDER BY distance DESC LIMIT 20 id | distance :-| -------: SELECT a.id ,a.distance FROM (Select id, st_distance_sphere(POINT(-82.337036, 29.645095 ), POINT(longitude, latitude ))/1000 as distance FROM users u WHERE id <> 3 HAVING distance < 50 ORDER BY distance DESC LIMIT 20) a WHERE a.id in (SELECT sender FROM matches WHERE status = 1) OR a.id NOT IN ( SELECT sender FROM matches UNION ALL SELECT receiver FROM matches ) ORDEr BY a.distance ASC id | distance :-| ------------------: 6 | 0.09663995445895139 7 | 0.14732089261518266
CREATE TABLE users (`id` varchar(5), `name` varchar(5), `longitude` varchar(11),
latitude varchar(11)) ;
latitude
INSERT INTO users (`id`, `name`, `longitude`, `latitude`) VALUES ('1', 'Mark', '-76.316528', '40.036027'), ('2', 'John', '-95.995102', '41.25716'), ('3', 'Paul', '-82.337036', '29.645095'), ('4', 'Dave', '-82.337036', '29.645095'), ('5', 'Chris', '-76.316528', '40.036027'), ('6', 'Manny', '-82.338036', '29.645095'), ('7', 'Fred', '-82.338036', '29.646095') ; ✓ ✓ CREATE TABLE matches (`id` int, `sender` int, `receiver` int, `status` int) ; INSERT INTO matches (`id`, `sender`, `receiver`, `status`) VALUES (1, 3, 4, 0), (2, 1, 5, 1), (3, 6, 3, 1) ; ✓ ✓ SELECT id , ( 3959 * acos( cos( radians(37) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-122) ) + sin( radians(37) ) * sin(radians(latitude)) ) ) AS distance FROM users HAVING distance < 50 ORDER BY distance DESC LIMIT 20 id | distance :-| -------: SELECT a.id ,a.distance FROM (Select id, st_distance_sphere(POINT(-82.337036, 29.645095 ),
POINT(longitude, latitude ))/1000 as distance FROM users u WHERE id <> 3 HAVING distance < 50 ORDER BY distance DESC LIMIT 20) a WHERE a.id in (SELECT sender FROM matches WHERE status = 1) OR a.id NOT IN ( SELECT sender FROM matches UNION ALL SELECT receiver FROM matches ) ORDEr BY a.distance ASC
longitude
sender
id | distance :-| ------------------: 6 | 0.09663995445895139 7 | 0.14732089261518266