SQL Group By i wybieranie drugiej najstarszej wartości

0

Witam,
Mam tabele z cenami zakupu towaru (partie), każda partie ma określoną datę przyjęcia.
ID_TOWARU CENA_ZAKUPU ILOSC DATA
1 1.44 3 2011-01-12
2 2.55 3 2011-01-12
3 5.44 4 2011-01-12
1 1.70 5 2011-01-13
1 1.63 6 2011-01-13
2 3.44 7 2011-01-13
2 5.42 4 2011-01-14
3 4.67 2 2011-01-14
3 5.41 1 2011-01-14

Oczywiście łatwo znaleźć najwyższą/najniższą cenę partii max(CENA_ZAKUPU)/min(CENA_ZAKUPU), łatwo jest znaleźć
najświeższą/najstarszą cenę partii max(DATA)/min(DATA).

Natomiast jak wyświetlić listę cen przedostatniej partii?

ID_TOWARU CENA_ZAKUPU ILOSC DATA
1 1.70 5 2011-01-13
2 3.44 7 2011-01-13
3 4.67 2 2011-01-14

0

Po pierwsze to nie widzę tutaj zastosowania GROUP BY o którym wspomniałeś w temacie.

A jeżeli chodzi o problem to zrobiłbym do tego procedurę z tabelą tymczasową. Pobierasz sobie wszystko sortując po id i dacie, pobierasz zawsze drugi wiersz dla danego id towaru i przechodzisz dalej aż znajdziesz inne id towaru, znowu pobierasz drugą itd. A wartości pobrane zapisujesz sobie do tabeli tymczasowej, którą na końcu zwracasz.

0

Nie napisałeś o jaką bazę chodzi. Można to ładnie zrobić analitycznymi funkcjami, w czystym sql'u już tak ładnie nie będzie.

0

Może faktycznie z tym Group By przegiąłem.
To znaczy gdyby była możliwość własnej definicji funkcji agregacyjnej typu Get2ndlast() to Group By tutaj by miało zastosowanie.

BAZA to MSSQL 2005, T-SQL dostępne (ale czy to konieczne?)

0

Mam pod ręką tylko oracle'a do sprawdzenia niestety.

 SQL> @@c:/sql/2.sql
SQL> create table partie (
  2    id_towaru integer,
  3    cena_zakupu number(10,2),
  4    ilosc integer,
  5    data date
  6  );

Table created.

SQL> 
SQL> insert into partie values (1,1.44,3,to_date('2011-01-12','YYYY-MM-DD'));

1 row created.

SQL> insert into partie values (2,2.55,3,to_date('2011-01-12','YYYY-MM-DD'));

1 row created.

SQL> insert into partie values (3,5.44,4,to_date('2011-01-12','YYYY-MM-DD'));

1 row created.

SQL> insert into partie values (1,1.70,5,to_date('2011-01-13','YYYY-MM-DD'));

1 row created.

SQL> insert into partie values (1,1.63,6,to_date('2011-01-13','YYYY-MM-DD'));

1 row created.

SQL> insert into partie values (2,3.44,7,to_date('2011-01-13','YYYY-MM-DD'));

1 row created.

SQL> insert into partie values (2,5.42,5,to_date('2011-01-14','YYYY-MM-DD'));

1 row created.

SQL> insert into partie values (3,4.67,2,to_date('2011-01-14','YYYY-MM-DD'));

1 row created.

SQL> insert into partie values (3,5.41,7,to_date('2011-01-14','YYYY-MM-DD'));

1 row created.

SQL> 
SQL> select id_towaru, cena_zakupu, ilosc,data
  2    from (select p.*, row_number() over (partition by p.id_towaru order by p.data desc, p.rowid desc) rn
  3  	       from partie p)
  4   where rn = 2;

 ID_TOWARU CENA_ZAKUPU      ILOSC DATA                                          
---------- ----------- ---------- --------                                      
         1         1,7          5 11/01/13                                      
         2        3,44          7 11/01/13                                      
         3        4,67          2 11/01/14                                      

SQL> 
SQL> drop table partie;

Table dropped.

SQL> exit

Oczywiście w t-sql też jest http://msdn.microsoft.com/pl-pl/library/ms186734.aspx.
Można się obyć bez rowid (którego zresztą nie ma dla sql servera), ale wtedy dostaniesz dla ID_TOWARU = 3 inną wartość niż chciałeś.
Zauważ, że w wypadku dwóch wpisów dla danego id z tą samą datą, nie masz jak rozróżnić który było wcześniej.

0

Super, ROW_NUMBER() dobrze robi czarną robotę ;).
Dzięki panowie ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1