1
votes

Requête pour marquer si une valeur se situe entre un ensemble de valeurs

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


0 commentaires

3 Réponses :


1
votes

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


0 commentaires

2
votes

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


0 commentaires

2
votes

Pour ce faire, vous pouvez générer un tableau des valeurs 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

Output:

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

Démo sur dbfiddle


2 commentaires

Merci, c'est parfait


@alwaystrying pas de soucis. Je suis heureux d'avoir pu aider.