1

Temat: Funkcja, która zwraca tabelę o zadanym schemacie

Witam,
mam do napisania funkcję która zwraca tabelę (miesiac int, rok int, wynik decimal(10,2)), gdzie  miesiąc odpowiada  miesiącom z tabel  rok2004  i  rok2005, rok przyjmuje jedna z wartości 2004 oraz 2005, a kolumna wynik ma wartość równa maksimum z 
wyników za rok 2004 i 2005 za dany miesiąc.

Mianowicie utworzyłem 2 tabele z rok2004 i rok2005 z odpowiednimi polami, jak teraz odwołać się do nich i utworzyć nową tabelę?

jedna z przykładowych tabeli:

CREATE TABLE rok2004
(
  miesiac integer,
  wynik numeric(10,2)
)

Próbowałem coś robić, ale straszne bzdury mi wychodzą. Można prosić jakieś wskazówki?

2

Odp: Funkcja, która zwraca tabelę o zadanym schemacie

Myślę, że zamiast pisania funkcji, w dodatku zwracającej tabelę można to załatwić względnie prostym zapytaniem. Bardziej warto się skupić nad dospecyfikowaniem, co ma zostać zwrócone jeżeli dla danego miesiąca wyniki są jednakowe z obydwu tabel ? Można założyć, że bierzemy wtedy pierwszy rok, czyli 2004. Druga kwestia, to czy obydwie tabele będą miały wypełnione wartości dla wszystkich 12 miesięcy, a w szczególności czy kolumna wynik w obydwu tabelach powinna posiadać constraint NOT NULL ?. Abstrahując od tej ostatniej kwestii można zrobić to tak:

-- Create (or replace) data structure:
Drop Table If Exists rok2004, rok2005;
Create Table rok2004
(
  miesiac integer,
  wynik numeric(10, 2)
);
Create Table rok2005
(
  miesiac integer,
  wynik numeric(10, 2)
);

-- Fill with random (0, 100) data for every month
Insert Into rok2004
    Select m, random()*100 From generate_series(1, 12) m;
Insert Into rok2005
    Select m, random()*100 From generate_series(1, 12) m;

Podgląd wartości wygenerowanego zestawu danych:

Select miesiac, rok2004.wynik As rok2004, rok2005.wynik As rok2005
From rok2004 Join rok2005 Using (miesiac)
Order by miesiac;
 miesiac | rok2004 | rok2005 
---------+---------+---------
       1 |   40.62 |   60.70
       2 |   25.56 |   86.56
       3 |   52.11 |   77.74
       4 |   73.69 |   98.81
       5 |   92.20 |   21.99
       6 |   98.04 |   17.74
       7 |   21.41 |   52.56
       8 |   23.65 |   12.97
       9 |   97.58 |   78.34
      10 |   10.16 |   79.71
      11 |   10.61 |   65.85
      12 |   46.59 |   68.57
(12 rows)

Docelowe zapytanie:

Select
    miesiac,
    Case When rok2004.wynik >= rok2005.wynik Then 2004 Else 2005 End As rok,
    Greatest(rok2004.wynik, rok2005.wynik) As wynik
From
    rok2004 Join rok2005 Using (miesiac)
Order by
    miesiac;
 miesiac | rok  | wynik 
---------+------+-------
       1 | 2005 | 60.70
       2 | 2005 | 86.56
       3 | 2005 | 77.74
       4 | 2005 | 98.81
       5 | 2004 | 92.20
       6 | 2004 | 98.04
       7 | 2005 | 52.56
       8 | 2004 | 23.65
       9 | 2004 | 97.58
      10 | 2005 | 79.71
      11 | 2005 | 65.85
      12 | 2005 | 68.57
(12 rows)

Jeżeli potrzebujesz także wypełnić docelową tabelę, to nic prostszego:

Drop Table If Exists rok_zestawienie;
Create Table rok_zestawienie (
    miesiac int,
    rok int,
    wynik decimal(10, 2)
);
Insert Into rok_zestawienie (miesiac, rok, wynik)
    Select
        miesiac,
        Case When rok2004.wynik >= rok2005.wynik Then 2004 Else 2005 End As rok,
        Greatest(rok2004.wynik, rok2005.wynik) As wynik
    From
        rok2004 Join rok2005 Using (miesiac)
    Order by
        miesiac;

Zrzut tabeli:

Table rok_zestawienie;
 miesiac | rok  | wynik 
---------+------+-------
       1 | 2005 | 60.70
       2 | 2005 | 86.56
       3 | 2005 | 77.74
       4 | 2005 | 98.81
       5 | 2004 | 92.20
       6 | 2004 | 98.04
       7 | 2005 | 52.56
       8 | 2004 | 23.65
       9 | 2004 | 97.58
      10 | 2005 | 79.71
      11 | 2005 | 65.85
      12 | 2005 | 68.57
(12 rows)

Ostatnio edytowany przez gszpetkowski (2011-12-21 22:53:14)