【问题标题】:MySQL request for combining and searching in 2 tablesMySQL请求在2个表中组合和搜索
【发布时间】:2020-02-04 20:31:18
【问题描述】:

我有 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 FROMusersHAVING distance < 50 ORDER BY distance DESC LIMIT 20

另一个matches是这样的:

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

其中 sender 是发送邀请的人,receiver 是接收者。

SQL 请求应在users 中搜索附近的人,并在matches 中检查他们的ID。如果 ID 不存在,则作为发送者和接收者返回此人的用户 ID 以建立新连接。

例如,Paul 正在搜索附近的人,而我们从 users 看到的 Dave 就在他附近。所以 Dave ID 应该只返回给 Paul,如果他们的 id 不在 matches table OR Paul == receiver AND status == 0 中。

应该如何编写这个 SQL 查询来返回附近人的 20 个 ID?

【问题讨论】:

    标签: mysql sql


    【解决方案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
    
    编号 |距离 :- | --------:
    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
    
    编号 |距离 :- | ------------------: 6 | 0.09663995445895139 7 | 0.14732089261518266

    db小提琴here

    【讨论】:

    • 谢谢!我怎么能联系到你?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2014-08-07
    • 1970-01-01
    相关资源
    最近更新 更多