Oracle
 sql >> Base de données >  >> RDS >> Oracle

Comment puis-je effectuer une interpolation linéaire à l'aide d'Oracle SQL ?

Je ne sais pas comment vous utiliseriez PERCENTILE_CONT pour faire l'interpolation que vous demandez, mais avec l'aide d'une fonction analytique différente, vous pouvez obtenir ce que vous voulez.

Tout d'abord, nous allons créer la fonction suivante, qui convertit INTERVAL DAY TO SECOND valeurs en secondes :

CREATE OR REPLACE FUNCTION intvl_to_seconds(
    p_interval INTERVAL DAY TO SECOND
) RETURN NUMBER DETERMINISTIC
AS
BEGIN
  RETURN EXTRACT(DAY FROM p_interval) * 24*60*60
       + EXTRACT(HOUR FROM p_interval) * 60*60
       + EXTRACT(MINUTE FROM p_interval) * 60
       + EXTRACT(SECOND FROM p_interval);
END;
/

Avec cette fonction, nous pouvons utiliser une requête telle que la suivante :

SELECT d1.time,
       d1.value AS value1,
       q2.prev_value + intvl_to_seconds(d1.time - q2.prev_time) * (q2.next_value - q2.prev_value)/intvl_to_seconds(q2.next_time - q2.prev_time) AS value2
  FROM devices d1
  LEFT OUTER JOIN (SELECT d2.time AS prev_time,
                          d2.value AS prev_value,
                          LEAD(d2.time, 1) OVER (ORDER BY d2.time) AS next_time,
                          LEAD(d2.value, 1) OVER (ORDER BY d2.time) AS next_value
                     FROM devices d2
                    WHERE d2.deviceid = 2) q2
               ON d1.time BETWEEN q2.prev_time AND q2.next_time
 WHERE d1.deviceid = 1;

J'ai pris vos données ci-dessus, défini le composant de date des horodatages sur aujourd'hui, et j'ai obtenu les résultats suivants lorsque j'ai exécuté la requête ci-dessus :

TO_CHAR(D1.TIME)                          VALUE1     VALUE2
------------------------------------- ---------- ----------
09-SEP-11 01.00.00.000000                      1
09-SEP-11 01.00.01.000000                   1.03 552.517625
09-SEP-11 01.00.02.000000                  1.063 552.404813

(J'ai ajouté un TO_CHAR vers d1.time pour réduire les espaces excessifs dans SQL*Plus.)

Si vous utilisez DATE s au lieu de TIMESTAMP s, vous n'avez pas besoin de la fonction :vous pouvez simplement soustraire les dates.