J'ai deux tables. Et je veux vérifier si une valeur de l'un se situe entre deux nombres quelconques de l'autre table. Par exemple, les tables sont:
Result: +--------+--------------+---------------------+---------------------+ | name | count | time_before | time_after | +--------+--------------+---------------------+---------------------+ | table1 | Counts Match | 2019-05-03 12:30:00 | 2019-05-03 13:30:00 | +--------+--------------+---------------------+---------------------+
À partir de là, je veux obtenir la valeur la plus proche au-dessus et en dessous du nombre dans table_b qui existe dans table_a, puis l'afficher comme une "correspondance", puis aussi afficher les heures de la valeur la plus proche au-dessus et en dessous de ce nombre. Donc, les résultats devraient ressembler à quelque chose de similaire à:
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 | +--------+-------+
Si cela ne correspond pas, alors il affichera cela dans les résultats comme ne correspondant pas et les heures seront simplement vides.
Merci
3 Réponses :
Une méthode est une jointure latérale:
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
Vous pouvez générer la liste des décomptes de début / fin (et des horodatages) à l'aide d'une fonction de fenêtre, puis la joindre à la deuxième table:
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;
Exemple en ligne: https://rextester.com/MBYZYU33789
Pour ce faire, vous pouvez générer un tableau des valeurs Output: avant et après pour count et time dans table_a , puis JOIN à table_b de telle sorte que table_b.count soit compris entre count_before code > et count_after:name count time_before time_after
table1 30,40 2019-05-03T12:30:00.000Z 2019-05-03T13:30:00.000Z
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
Merci, c'est parfait
@alwaystrying pas de soucis. Je suis heureux d'avoir pu aider.