1

Temat: porównanie wartości z dwóch tabel przy użyciu pythona

Witam, mam problem ze zrobieniem zadania na zajęcia. Mam dwie tabele rok2004 i rok2005, w każdej jest miesiąc jako int i wynik, i muszę porównać te wyniki i w zależności który jest większy wpisać do trzeciej tabeli wraz z numerem miesiąca i rokiem. Zrobiłam coś takiego:

CREATE OR REPLACE FUNCTION compare()
  RETURNS trigger AS
$BODY$CREATE OR REPLACE FUNCTION increment(i integer = 1) RETURNS integer AS $$
        BEGIN
        i=1
        while i<13:
                a=(select wynik from rok2004 where miesiac = 'i')
                b=(select wynik from rok2005 where miesiac = 'i')
                if a>b:
            INSERT INTO wyniki values (i, 2004, (select wynik from rok2004 where miesiac = i)
        else:
            INSERT INTO wyniki values (i, 2005, (select wynik from rok2005 where miesiac = i)
        END;
$$ LANGUAGE plpythonu;

Zapytanie wykonuje się, nie wyrzuca błędów ale też w tabeli wyniki nadal jest pusto. Ktoś wie co mogę z tym zrobić? Jak poprawić?

2

Odp: porównanie wartości z dwóch tabel przy użyciu pythona

niestety nie znal pythona ale samo rozwiązanie można zrealizować tak:
INSERT INTO wyniki (miesiac,rok,wynik)
select
  miesiac.miesiac
, case when coalesce(r4.wynik,0)>=coalesce(r5.wynik,0) then 2004 else 2005 end as rok
, case when coalesce(r4.wynik,0)>=coalesce(r5.wynik,0) then r4.wynik else r5.wynik end as wynik
from generate_series(1,12) miesiac
left join rok2004 r4 on miesiac.miesiac=r4.miesiac
left join rok2005 r5 on miesiac.miesiac=r5.miesiac;

3

Odp: porównanie wartości z dwóch tabel przy użyciu pythona

Python wydaje mi się nieistotny. Można to zrobić prostym zapytaniem. Jedną wersję podał c_michał. Możesz jeszcze na co najmniej dwa sposoby:

insert into wyniki (miesiac, rok, wynik)
select
    coalesce( r4.miesiac, r5.miesiac),
    case when coalesce(r4.wynik,0)>=coalesce(r5.wynik,0) then 2004 else 2005 end,
    case when coalesce(r4.wynik,0)>=coalesce(r5.wynik,0) then r4.wynik else r5.wynik end
from
    rok2004 as r4
    full outer join rok2005 as r5 using (miesiac)

To jest modyfikacja pomysłu c_michała. Należy tylko mieć świadomość faktu, że nie nie zadziała poprawnie jeśli możesz mieć ujemne wyniki.

Alternatywa:

insert into wyniki (miesiac, rok, wynik)
select
    distinct on (miesiac) *
from (
    select miesiac, 2004 as rok, wynik from rok2004
    union all
    select miesiac, 2005 as rok, wynik from rok2005
) as polaczone
order by miesiac, wynik desc;
--
The best thing about modern society is how easy it is to avoid contact with it.

4

Odp: porównanie wartości z dwóch tabel przy użyciu pythona

5

Odp: porównanie wartości z dwóch tabel przy użyciu pythona

@c_michal:

Szczerze mówiąc nie jestem pewien czemu to działa tak jak działa dla 2004/2005.

Ogólnie - jeśli nie sortujesz wyniku po jakimś polu, to baza danych może zwrócić "losowy" wynik. Dlaczego dla tego zapytania akurat zawsze zwraca mniejszą wartość - trzeba by poszukać w kodzie, ale to nie ma za bardzo sensu - i tak nie można by na takiej "logice" polegać, bo zawsze może być zmieniona.

Natomiast co do finalnego zapytania - podwójne sortowanie nie daje gwarancji. Lepiej:

with rok2004 (miesiac,wynik) as (values (1,1),(2,2)      ,(4,4),(5,null),(6,6))
    ,rok2005 (miesiac,wynik) as (values (1,3)      ,(3,3),(4,5)         ,(6,6))
select
    distinct on (miesiac) *
from (
    select miesiac, 2004 as rok, wynik from rok2004
    union all
    select miesiac, 2005 as rok, wynik from rok2005
) as polaczone
order by miesiac, wynik desc, rok asc;
--
The best thing about modern society is how easy it is to avoid contact with it.

6

Odp: porównanie wartości z dwóch tabel przy użyciu pythona

Co do finalnego zapytania to masz 100% racji, ale swoją drogą ciekawe zachowanie bazy smile

7

Odp: porównanie wartości z dwóch tabel przy użyciu pythona

Zadałem pytanie na ircu, i na liście mailingowej. Zobaczymy czy będzie odzew. Realnie - trzeba by pewnie zajrzeć mocno do kodu sortującego. Na liście pojawiła się sugestia, że może to być związane z ilością rekordów. RhodiumToad pokazał, że jak skasuje się rekord (1,1), to wyniki się zmieniają (jak się zmieni kolejność subselectów w unionie).

Tak czy inaczej - zgadzam się z ludźmi z irca - wnikanie ma pewien sens jako "gra umysłowa", ale wtedy trzeba samemu usiąść ze źródłami, debuggerem i piwem. Aż tak mi się nie nudzi smile

--
The best thing about modern society is how easy it is to avoid contact with it.