一尘不染

MySQL要求在2个表格中进行合并和搜索

sql

我有2张桌子。我的其中一张表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

另一个matches是这样的:

id         sender    receiver        status  
-----      -----    -----------    -----------

发送者是发送邀请者的人,接收者是接收者的人。

SQL请求应在users人员附近搜索并检查matchesID。如果没有作为发送者和接收者的ID,则返回此人的用户ID以建立新的连接。

例如,保罗在寻找附近的人,而戴夫users则在他附近寻找。因此,仅当Dave ID不在matches表中或Paul == receiverAND
status == 0时,才应将Dave ID返回给Paul 。

如何编写此SQL查询以返回附近人员的20个ID?


阅读 181

收藏
2021-05-05

共1个答案

一尘不染

我将距离公式更改为自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
2021-05-05