У меня есть две таблицы. И я хочу проверить, находится ли значение от одного, между любыми двумя числами в другой таблице. Например таблицы:

table_a:
+--------+-------+---------------------+
|  name  | count |        time         |
+--------+-------+---------------------+
| table1 | 10    | 2019-05-03 10:30:00 |
| table1 | 20    | 2019-05-03 11:30:00 |
| table1 | 30    | 2019-05-03 12:30:00 |
| table1 | 40    | 2019-05-03 13:30:00 |
| table1 | 50    | 2019-05-03 14:30:00 |
+--------+-------+---------------------+

table_b:
+--------+-------+
|  name  | count |
+--------+-------+
| table1 | 35    |
+--------+-------+

Из этого я хочу получить самое близкое значение выше и ниже числа в table_b, которое существует в table_a, а затем показать это как «соответствие», а затем также отобразить времена ближайшего значения выше и ниже этого числа. Таким образом, результаты должны выглядеть примерно так:

Result:
+--------+--------------+---------------------+---------------------+
|  name  |    count     |     time_before     |     time_after      |
+--------+--------------+---------------------+---------------------+
| table1 | Counts Match | 2019-05-03 12:30:00 | 2019-05-03 13:30:00 |
+--------+--------------+---------------------+---------------------+

Если это не совпадает, то в результатах будет показано, что оно не совпадает, а время будет пустым.

Спасибо

1
alwaystrying 3 Май 2019 в 13:57

3 ответа

Лучший ответ

Вы можете сделать это, сгенерировав таблицу из before и after значений для count и time в table_a, а затем JOIN ее в table_b так, что table_b.count находится между count_before и count_after:

SELECT a.name, 
       a.count_before || ',' || a.count_after  AS count,
       a.time_before,
       a.time_after
FROM (SELECT name,
             lag(count) over (order by time) AS count_before,
             count AS count_after,
             lag(time) over (order by time) AS time_before,
             time AS time_after
      FROM table_a) a
JOIN table_b b ON b.count BETWEEN a.count_before AND a.count_after

Выход:

name    count   time_before                 time_after
table1  30,40   2019-05-03T12:30:00.000Z    2019-05-03T13:30:00.000Z

Демо на dbfiddle

2
Nick 3 Май 2019 в 11:15

Вы можете сгенерировать список начальных / конечных отсчетов (и временных меток) с помощью оконной функции, а затем соединить это со второй таблицей:

with ranges as ( 
  select name, 
         "time" as time_start,
         "count" as count_start, 
         lead("count") over w as count_end, 
         lead("time") over w as time_end
  from table_a
  window w as (partition by name order by "time")
)
select t2.name, t2."count", r.count_start, r.count_end, r.time_start, r.time_end
from table_b t2 
  join ranges r on r.name = t2.name and t2."count" between r.count_start and r.count_end;

Пример в Интернете: https://rextester.com/MBYZYU33789

2
a_horse_with_no_name 3 Май 2019 в 11:14

Одним из методов является боковое соединение:

select b.*, a.lower, a.upper
from table_b b cross join lateral
     (select max(lower) as lower, max(upper) as upper
      from ((select a.time as lower, null as upper
             from table_a a
             where a.value <= b.value
             order by b.time desc
             fetch first 1 row only
            ) union all
            (select null as lower, a.time as upper
             from table_a a
             where a.value >= b.value
             order by b.time asc
             fetch first 1 row only
            )
           ) a
      ) a
1
Gordon Linoff 3 Май 2019 в 11:01