Использование BETWEEN SYMMETRIC для проверки 2 выражений значения строки - PullRequest
0 голосов
/ 27 сентября 2019

Я хотел бы сравнить два значения столбцов из 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' 

ЗАДАЧА:

Цель состоит в том, чтобы получить все строки, для которых lat или lon (или оба) в таблице location соответствуют критериям (в таблице trips): lat между lat_start-lat_end;lon между lon_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        |
+---------+-----------+------+-----+-------------+

Запрос-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       |
+---------+-----------+------+-----+-------------+

Запрос-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       |
+---------+-----------+------+-----+-------------+

Вопрос: Какой правильный запрос для достижения желаемого результата?

РЕДАКТИРОВАТЬ:

Исходя из полученных ответов, рекомендуя использовать OR вместо AND в Query-1, я редактирую свой вопрос ниже, чтобы показать результат рекомендуемого запроса:

QUERY:

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       |
+---------+-----------+------+-----+-------------+

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Цель состоит в том, чтобы получить все строки, для которых либо широта, либо долгота (или оба) в таблице местоположений соответствуют критериям

Заменить AND на OR в вашемпервый запрос.

0 голосов
/ 27 сентября 2019

Запрос, который вы ищете:

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)?

Сравнение кортежей выполняется в

Сначала сравниваются a и c, и только если они равны, сравниваются b и d.

Итак

(a, b) < (c, d)

- это то же самое, что

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

Так что это совсем не то, что вы ищете.

...