【问题标题】:Using BETWEEN SYMMETRIC for checking 2 row value expressions使用 BETWEEN SYMMETRIC 检查 2 行值表达式
【发布时间】:2019-09-27 11:50:20
【问题描述】:

我想比较来自Table-1(比如colA, colX)的两列值,以检查它们是否在Table-2(比如colB, colD, colY, colZ)的列值范围内。也就是说,如果colA 介于colB-colD 之间,和/或colX 分别介于colY-colZ 之间。

我知道BETWEEN SYMMETRIC 在订单无关紧要时使用,例如(最小,最大)或(最大,最小)。下面是我创建的示例。

表格:

CREATE TABLE location (id int, lat float, lon float, gpstime int);
CREATE TABLE trips( trip_id int, lat_start float, lat_end float,
               lon_start float, lon_end float, travel_mode text);

表值:

INSERT INTO location
SELECT 1, 41.2, 8.3, 11111 UNION ALL   --both lat and lon in the interval
SELECT 2, 43.3, 8.5, 22222 UNION ALL   --only lat meets criteria
SELECT 3, 44.0, 8.5,  33333            --only lon meets criteria

INSERT INTO trips
SELECT 1, 41.1, 41.9, 8.0, 8.8, 'foot' UNION ALL  
SELECT 2, 43.1, 43.5, 9.5, 8.9, 'bus' UNION ALL
SELECT 3, 42.1, 42.8, 8.7, 8.0, 'metro' 

任务:

目标是获取location 表中latlon(或两者)碰巧满足条件的所有行(在trips 表中):latlat_start-lat_end 之间; lonlon_start- lon_end 之间。

显然应该返回location 表的所有行:第 1 行满足所有条件,第 2 行和第 3 行满足任一条件。

预期结果:

+---------+-----------+------+-----+-------------+
| trip_id | timestamp | lat  | lon | travel_mode |
+---------+-----------+------+-----+-------------+
|       1 |     11111 | 41.2 | 8.3 | foot        |
|       2 |     22222 | 43.1 | 8.5 | bus         |
|       3 |     33333 | 44.0 | 8.5 | metro       |
+---------+-----------+------+-----+-------------+

所以我使用BETWEEN SYMMETRIC 尝试了不同的查询,但结果不正确。

查询-1:

SELECT trip_id, gpstime AS timestamp, lat, lon,  travel_mode
FROM location 
INNER JOIN trips 
   ON (lat BETWEEN SYMMETRIC lat_start AND lat_end) 
   AND (lon BETWEEN SYMMETRIC lon_start AND lon_end) 

查询结果:

+---------+-----------+------+-----+-------------+
| trip_id | timestamp | lat  | lon | travel_mode |
+---------+-----------+------+-----+-------------+
|       1 |     11111 | 41.2 | 8.3 | foot        |
+---------+-----------+------+-----+-------------+

Query-2:搞砸了一切

SELECT trip_id, gpstime AS timestamp, lat, lon,  travel_mode
FROM location 
INNER JOIN trips 
   ON (lat, lon) BETWEEN SYMMETRIC (lat_start,  lat_end) AND (lon_start, lon_end)

结果:

+---------+-----------+------+-----+-------------+
| trip_id | timestamp | lat  | lon | travel_mode |
+---------+-----------+------+-----+-------------+
|       2 |     11111 | 41.2 | 8.3 | foot        |
|       3 |     11111 | 41.2 | 8.3 | metro       |
+---------+-----------+------+-----+-------------+

Query-3:最差的情况

SELECT trip_id, gpstime AS timestamp, lat, lon,  travel_mode
FROM location 
INNER JOIN trips 
   ON lat BETWEEN SYMMETRIC lat_start AND lat_end
UNION 
SELECT trip_id, gpstime AS timestamp, lat, lon,  travel_mode
FROM location 
INNER JOIN trips 
   ON lon BETWEEN SYMMETRIC lon_start AND lon_end

结果:

+---------+-----------+------+-----+-------------+
| trip_id | timestamp | lat  | lon | travel_mode |
+---------+-----------+------+-----+-------------+
|       1 |     11111 | 41.2 | 8.3 | foot        |
|       1 |     22222 | 43.3 | 8.5 | foot        |
|       1 |     33333 | 44   | 8.5 | foot        |
|       2 |     22222 | 43.3 | 8.5 | bus         |
|       3 |     11111 | 41.2 | 8.3 | metro       |
|       3 |     22222 | 43.3 | 8.5 | metro       |
|       3 |     33333 | 44   | 8.5 | metro       |
+---------+-----------+------+-----+-------------+

问题:什么是达到预期结果的正确查询?

编辑:

根据收到的答案,建议在 Query-1 中使用 OR 而不是 AND,我在下面编辑我的问题以显示推荐查询的结果:

查询:

SELECT trip_id, gpstime AS timestamp, lat, lon,  travel_mode
FROM location 
INNER JOIN trips 
   ON (lat BETWEEN SYMMETRIC lat_start AND lat_end) 
   OR (lon BETWEEN SYMMETRIC lon_start AND lon_end);

查询结果如下:

+---------+-----------+------+-----+-------------+
| trip_id | timestamp | lat  | lon | travel_mode |
+---------+-----------+------+-----+-------------+
|       1 |     11111 | 41.2 | 8.3 | foot        |
|       3 |     11111 | 41.2 | 8.3 | metro       |
|       1 |     22222 | 43.3 | 8.5 | foot        |
|       2 |     22222 | 43.3 | 8.5 | bus         |
|       3 |     22222 | 43.3 | 8.5 | metro       |
|       1 |     33333 | 44   | 8.5 | foot        |
|       3 |     33333 | 44   | 8.5 | metro       |
+---------+-----------+------+-----+-------------+

【问题讨论】:

    标签: sql postgresql resultset between


    【解决方案1】:

    目标是获取所有包含 lat 或 lon(或两者)的行 位置表恰好满足条件

    在您的第一个查询中将 AND 替换为 OR

    【讨论】:

    • 生成类似于 Query-3 的内容,产生 7 行。
    【解决方案2】:

    您要查找的查询是

    SELECT trip_id, gpstime AS timestamp, lat, lon,  travel_mode
    FROM location 
    INNER JOIN trips 
       ON (lat BETWEEN SYMMETRIC lat_start AND lat_end) 
       OR (lon BETWEEN SYMMETRIC lon_start AND lon_end);
    

    就像萨尔曼说的,但让我帮你消除误会。

    BETWEEN SYMMETRIC 是什么意思?

    x BETWEEN SYMMETRIC a AND b
    

    一样
    x BETWEEN SYMMETRIC LEAST(a, b) AND GREATEST(a, b)
    

    所以它只是在适当的时候交换边界。

    (a, b) < (c, d) 是什么意思?

    比较元组以字典方式完成。

    首先,比较ac,只有当它们相等时,才比较bd

    所以

    (a, b) < (c, d)
    

    一样
    a < c OR (a = c AND b < d)
    

    所以这根本不是你要找的。​​p>

    【讨论】:

    • 使用 OR 生成类似于 query-3 的结果。我编辑我的问题以显示生成的结果。
    • 是的。这正是您在问题中描述的“任务”。
    • 我想获得问题的“预期结果”部分中显示的结果集。
    • 哦,现在我明白了。您认为一个表的第一行与另一个表的第一行连接,依此类推。您应该阅读有关 SQL 连接的信息。解释所有这些远远超出了 Stackoverflow 答案的格式。一方面,表格行没有顺序,因此“表格中的第一行”没有明确的含义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 2016-10-19
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多