2010-01-04 9 views
12

Mam poniższej tabeli w Oracle DBOracle zapytanie SQL: Pobierz najnowsze wartości na grupy na podstawie czasu

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 

teraz chciałbym, aby pobrać najnowszą wartość (i jego czasu) na identyfikatorze. Przykładowy wynik:

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 

po prostu nie może dowiedzieć się, jak umieścić, że w zapytaniu ...

dodatkowo następujące opcje byłoby miło:

Wariant 1: kwerenda powinien jedynie zwraca wartości z ostatnich 20 minut.

Opcja 2: identyfikator powinien być łączony z tekstem z innej tabeli, która ma id i idname. wyjście dla id powinno być wtedy takie jak: id-idname (np. 1-testid1).

wielkie dzięki za pomoc!

+0

Czy "DATA" jest unikalna dla danego "ID"? – APC

+0

Znacznik czasu powinien być unikalny, ale najwyraźniej nie ma go w dostępnych danych - dlatego rozwiązanie powinno działać niezależnie. – Tom

Odpowiedz

21

Biorąc pod uwagę te dane ...

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> 

... następujące zapytanie daje to, co chcesz ...

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> 

W odniesieniu do swoich wymagań dodatkowych, można zastosować dodatkowe filtry do zewnętrznej WHERE. Podobnie możesz dołączyć dodatkowe tabele do widoku śródliniowego, tak jak każda inna tabela.

+0

dzięki, podstawowe zapytanie działa poprawnie. Właśnie okazało się, że znacznik czasu nie zawsze jest unikalny, więc mam wiele wpisów na identyfikator, ale dodanie DISTINCT na początek pomogło. spróbuje teraz dodatkowych opcji. – Tom

+0

Czy lepiej byłoby dodać DISTINCT do wyboru wewnętrznego lub zewnętrznego? – Tom

+0

DISTINCT nie zmieni uzyskanych wyników, chyba że przypadkiem wartości "quantity" są zgodne z maksymalnymi wartościami "date". Musisz odkryć, jaka jest właściwa reguła biznesowa i zastosować ją. Możliwości obejmują 'max (ilość)', 'min (ilość)' lub 'avg (ilość)', ale istnieje wiele możliwych rozwiązań. – APC

6

Oto pełny, przetestowany przykład.

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 

Wyniki:

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 

Jeśli chcesz uzyskać rekordy z ostatnich XX minut, można to zrobić (używam 500 minut w tym przykładzie, należy wymienić 500 z cokolwiek pragnienie):

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

Głosowałem również za Twoją odpowiedzią, po prostu wolę składnię innego stwierdzenia. – Tom

Powiązane problemy