2010-01-04 4 views
12

J'ai le tableau suivant dans une base de données OracleOracle requête SQL: Récupérer les dernières valeurs par groupe en fonction du temps

id  date    quantity 
1  2010-01-04 11:00 152 
2  2010-01-04 11:00 210 
1  2010-01-04 10:45 132 
2  2010-01-04 10:45 318 
4  2010-01-04 10:45 122 
1  2010-01-04 10:30 1 
3  2010-01-04 10:30 214 
2  2010-01-04 10:30 5515 
4  2010-01-04 10:30 210 

maintenant je voudrais récupérer la dernière valeur (et son temps) par id. Exemple de sortie:

id  date    quantity 
1  2010-01-04 11:00 152 
2  2010-01-04 11:00 210 
3  2010-01-04 10:30 214 
4  2010-01-04 10:45 122 

Je ne peux pas comprendre comment mettre cela en une requête ...

De plus, les options suivantes serait bien:

Option 1: la requête doit seulement renvoie les valeurs des dernières XX minutes.

Option 2: l'ID doit être concaténé avec le texte d'une autre table qui a id et idname. La sortie pour id devrait alors être comme: id-idname (par exemple 1-testid1).

un grand merci pour toute aide!

+0

'DATE' est-il unique pour un' ID' donné? – APC

+0

l'horodatage doit être unique, mais apparemment il ne figure pas dans les données dont je dispose - la solution devrait donc fonctionner indépendamment. – Tom

Répondre

21

Compte tenu de ces données ...

SQL> select * from qtys 
    2/

     ID TS      QTY 
---------- ---------------- ---------- 
     1 2010-01-04 11:00  152 
     2 2010-01-04 11:00  210 
     1 2010-01-04 10:45  132 
     2 2010-01-04 10:45  318 
     4 2010-01-04 10:45  122 
     1 2010-01-04 10:30   1 
     3 2010-01-04 10:30  214 
     2 2010-01-04 10:30  5515 
     4 2010-01-04 10:30  210 

9 rows selected. 

SQL> 

... la requête suivante donne ce que vous voulez ...

SQL> select x.id 
    2   , x.ts as "DATE" 
    3   , x.qty as "QUANTITY" 
    4 from (
    5  select id 
    6    , ts 
    7    , rank() over (partition by id order by ts desc) as rnk 
    8    , qty 
    9  from qtys) x 
10 where x.rnk = 1 
11/

     ID DATE    QUANTITY 
---------- ---------------- ---------- 
     1 2010-01-04 11:00  152 
     2 2010-01-04 11:00  210 
     3 2010-01-04 10:30  214 
     4 2010-01-04 10:45  122 

SQL> 

En ce qui concerne vos besoins supplémentaires, vous pouvez appliquer des filtres supplémentaires à l'extérieur clause WHERE. De même, vous pouvez joindre des tables supplémentaires à la vue en ligne comme si c'était une autre table.

+0

merci, la requête de base fonctionne très bien. Je viens de découvrir que l'horodatage n'est pas toujours unique, donc j'ai reçu plusieurs entrées par identifiant, mais l'ajout d'un DISTINCT au début a aidé. va essayer les options supplémentaires maintenant. – Tom

+0

serait-il préférable, sur le plan des performances, d'ajouter le DISTINCT au sélecteur interne ou externe? – Tom

+0

DISTINCT ne modifiera pas les résultats obtenus, à moins que les valeurs 'quantity' ne correspondent par hasard aux valeurs maximum' date'. Vous devez découvrir la règle métier appropriée et l'appliquer. Les possibilités incluent 'max (quantité)', 'min (quantité)' ou 'avg (quantité)', mais il existe de nombreuses résolutions possibles. – APC

6

Voici un exemple complet et testé.

CREATE TABLE tbl1 (ID NUMBER, dt DATE, quantity NUMBER); 

DELETE FROM tbl1; 
insert into tbl1 values (1,to_date('2010-01-04 11:00','YYYY-MM-DD HH24:MI'), 152); 
insert into tbl1 values (2,to_date('2010-01-04 11:00','YYYY-MM-DD HH24:MI'), 210); 
insert into tbl1 values (1,to_date('2010-01-04 10:45','YYYY-MM-DD HH24:MI'), 132); 
insert into tbl1 values (2,to_date('2010-01-04 10:45','YYYY-MM-DD HH24:MI'), 318); 
insert into tbl1 values (4,to_date('2010-01-04 10:45','YYYY-MM-DD HH24:MI'), 122); 
insert into tbl1 values (1,to_date('2010-01-04 10:30','YYYY-MM-DD HH24:MI'), 1); 
insert into tbl1 values (3,to_date('2010-01-04 10:30','YYYY-MM-DD HH24:MI'), 214); 
insert into tbl1 values (2,to_date('2010-01-04 10:30','YYYY-MM-DD HH24:MI'), 5515); 
insert into tbl1 values (4,to_date('2010-01-04 10:30','YYYY-MM-DD HH24:MI'), 210); 

SELECT t.ID 
    , t.DT 
    , t.QUANTITY 
    FROM tbl1 t 
    ,(SELECT ID 
      , MAX(dt) dt 
      FROM tbl1 
     GROUP BY ID) t2 
    WHERE t.id = t2.id 
    AND t.dt = t2.dt 

Résultats:

1 1/4/2010 11:00:00 AM 152 
2 1/4/2010 11:00:00 AM 210 
3 1/4/2010 10:30:00 AM 214 
4 1/4/2010 10:45:00 AM 122 

Si vous souhaitez obtenir les enregistrements pour les dernières minutes XX, vous pouvez le faire (j'utilise 500 minutes dans cet exemple, remplacer les 500 avec tout ce que vous désir):

SELECT t.ID 
     , t.DT 
     , t.QUANTITY 
    FROM tbl1 t 
     ,(SELECT ID 
       , MAX(dt) dt 
      FROM tbl1 
      WHERE dt >= SYSDATE - (500/1400) 
      GROUP BY ID) t2 
    WHERE t.id = t2.id 
     AND t.dt = t2.dt; 
+0

J'ai voté pour votre réponse aussi, je préfère simplement la syntaxe de l'autre déclaration. – Tom

Questions connexes