2013-07-07 2 views
3

J'utilise PostgreSQL 9.1.9 x64 avec PostGIS 2.0.3 sous Windows Server 2008 R2.Trouver le prochain numéro le plus proche dans PostgreSQL

J'ai une table:

CREATE TABLE field_data.trench_samples (
    pgid SERIAL NOT NULL, 
    trench_id TEXT, 
    sample_id TEXT, 
    from_m INTEGER 
); 

Avec des données qu'il contient:

INSERT INTO field_data.trench_samples (
    trench_id, sample_id, from_m 
) 
VALUES 
    ('TR01', '1000001', 0), 
    ('TR01', '1000002', 5), 
    ('TR01', '1000003', 10), 
    ('TR01', '1000004', 15), 
    ('TR02', '1000005', 0), 
    ('TR02', '1000006', 3), 
    ('TR02', '1000007', 9), 
    ('TR02', '1000008', 14); 

Maintenant, ce que je suis intéressé est de trouver la différence (la distance en mètres dans cet exemple) entre un record "from_m" et "next" "from_m" pour ce trench_id.

Ainsi, sur la base des données ci-dessus, je voudrais terminer avec une requête qui produit le tableau suivant:

pgid, trench_id, sample_id, from_m, to_m, interval 
1, 'TR01', '1000001', 0, 5, 5 
2, 'TR01', '1000002', 5, 10, 5 
3, 'TR01', '1000003', 10, 15, 5 
4, 'TR01', '1000004', 15, 20, 5 
5, 'TR02', '1000005', 0, 3, 3 
6, 'TR02', '1000006', 3, 9, 6 
7, 'TR02', '1000007', 9, 14, 5 
8, 'TR02', '1000008', 14, 19, 5 

Maintenant, vous dites probablement « attendre, comment pouvons-nous en déduisons un intervalle longueur pour le dernier échantillon dans chaque ligne, puisqu'il n'y a pas de "next" from_m à comparer? "

Pour les "extrémités" des lignes (exemples d'échantillons 1000004 et 1000008), je voudrais utiliser la même longueur d'intervalle que les deux échantillons précédents.

Bien sûr, je ne sais pas comment aborder cela dans mon environnement actuel. Votre aide est très appréciée.

Répondre

1

Voici comment vous obtenez la différence, en utilisant le un exemple précédent à la fin (comme indiqué dans les données, mais pas clairement expliqué dans le texte).

La logique ici est l'application répétée de lead() et lag(). Appliquez d'abord lead() pour calculer l'intervalle. Ensuite, appliquez lag() pour calculer l'intervalle à la limite, en utilisant l'intervalle précédent.

Le reste est tout simplement arithmétique:

select trench_id, sample_id, from_m, 
     coalesce(to_m, 
       from_m + lag(interval) over (partition by trench_id order by sample_id) 
       ) as to_m, 
     coalesce(interval, lag(interval) over (partition by trench_id order by sample_id)) 
from (select t.*, 
      lead(from_m) over (partition by trench_id order by sample_id) as to_m, 
      (lead(from_m) over (partition by trench_id order by sample_id) - 
       from_m 
      ) as interval 
     from field_data.trench_samples t 
    ) t 

Here est le SQLFiddle montrant qu'il travaille.

+0

Un grand merci pour la réponse rapide! Quelle est la raison pour laquelle vous avez utilisé row_number plutôt que d'utiliser simplement la valeur stockée dans pgid sur insert? – Joebocop

+1

@Joebocop. . . Aucune bonne raison du tout. J'ai manqué le «serial» quand je répondais. –

+0

@Joebocop. . . Les fonctions fenêtre/analytique sont des fonctions très puissantes supportées par de nombreuses bases de données. Je suis content que vous ayez l'opportunité d'apprendre à leur sujet. –

Questions connexes