1

Temat: Zapytanie zamiast funkcji

Witam
Mam taka tabelke

nr_kolejny   nr_potrawy  nr_naczynia   naczynie_domyslne
     1                    1                    1                      tak
      2                    1                    2                     nie
      3                    1                    3                     nie
      4                    2                    2                      nie
      5                    2                    7                      nie

Chciałbym za pomocą zapytania nie tworząc funkcji wybrać po jednym rekordzie z każdej potrawy. Gdyby zawsze potrawa miała naczynie domyslne to nie było by problemu, ale nie zawsze tak jest. Chciałbym wybrać dla danej potrawy jej naczynie domyślne, a jeżeli takiego nie ma to naczynie dowolne dla tej potrawy.

Wynik miałby być taki

  1             1             1              tak
  4             2             2              nie   (lub drugi rekord dla tej potrawy, ponieważ nie ma ona naczynia domyślnego)


Z góry dzięki za pomoc
AdamP.

2

Odp: Zapytanie zamiast funkcji

Wyświetla tylko naczynie domyślne dla danej potrawy, działa na zasadzie spłaszczenia zbioru danych, wewnętrzny select grupujący wybiera dla danej potrawy i pola naczynie_domyslne najmniejsze nr_naczynia, drugi select przy założeniu, że dla danej wartości pola naczynie_domyslne już występuje tylko jedno naczynie, sumuje je i pokazuje w 2 kolumnach z których funkcja coalesce wybiera pierwszą nie null-ową wartość.

select nr_potrawy
      ,coalesce (sum(case when naczynie_domyslne is true then nr_naczynia else null end)
                ,sum(case when naczynie_domyslne is false then nr_naczynia else null end)) as naczynie_domyslne
from (
    select nr_potrawy,naczynie_domyslne,min(nr_naczynia) as nr_naczynia
    from (
          select 1 as nr_kolejny, 1 as nr_potrawy, 1 as nr_naczynia, true as naczynie_domyslne union all
          select 2 as nr_kolejny, 1 as nr_potrawy, 2 as nr_naczynia, false as naczynie_domyslne union all
              select 3 as nr_kolejny, 1 as nr_potrawy, 3 as nr_naczynia, false as naczynie_domyslne union all
          select 4 as nr_kolejny, 2 as nr_potrawy, 2 as nr_naczynia, false as naczynie_domyslne union all
              select 5 as nr_kolejny, 2 as nr_potrawy, 7 as nr_naczynia, false as naczynie_domyslne
         ) tab
       group by nr_potrawy,naczynie_domyslne
) d
group by nr_potrawy

3

Odp: Zapytanie zamiast funkcji

Dzięki za pomoc, nie działa tak jak chciałem, ale już jest jakiś trop.
W przykładzie powyżej brakuje from tabela przed union all, ale to tylko tak na marginesie

Na razie wykorzystuje taką funkcję, może ktoś ma lepszy pomysł.

CREATE OR REPLACE FUNCTION fpobierz_naczynie_do_potrawy (
  zm_nr_skladu_potrawy integer
)
RETURNS SETOF widok_catering_potrawy_naczynia AS
$body$
DECLARE   
r RECORD;
zmw_ilosc integer;
BEGIN
--- sprawdzam czy potrawa ma naczynie domyslne

    select nr_kolejny into zmw_ilosc from tab_catering_potrawy_naczynia where nr_potrawy = zm_nr_skladu_potrawy and naczynie_domyslne = TRUE;
    if not found then --- jezeli nie ma domyslnego lub zadnego
         FOR r IN SELECT * from widok_catering_potrawy_naczynia where nr_potrawy = zm_nr_skladu_potrawy order by nr_naczynia limit 1 LOOP  -- dowolne naczynie zwracam
            RETURN NEXT r;
        END LOOP;
        RETURN;
    else
        FOR r IN SELECT * from widok_catering_potrawy_naczynia where nr_potrawy = zm_nr_skladu_potrawy and naczynie_domyslne = TRUE LOOP
            RETURN NEXT r;
        END LOOP;
        RETURN;
      end if;
END;
$body$
LANGUAGE 'plpgsql'

Mam tylko mały problem, kiedy funkcja nie znajduje nic w widoku, to czy można sztucznie zwrócić rekord np:
return 0,1,112,'brak'  dostosowując kolejność i typ do rekordu z widoku na którym operuje funkcja??


AdamP.

4

Odp: Zapytanie zamiast funkcji

Jeśli chcesz zwracać domyślne wartości to dopisz sobie w funkcji kod:
FOR r IN SELECT 0::integer,1::integer,112::integer,'brak'::varchar(100) LOOP
       RETURN NEXT r;
END LOOP;
RETURN;
konwersja typów chyba jest konieczna i powinna być dostosowana do tego co masz w widoku widok_catering_potrawy_naczynia (nie sprawdzałem tego do końca więc musisz się pobawić) no chyba, że zadeklarujesz zmienną r jako typu "widok_catering_potrawy_naczynia", a nie record.

PS
Widzę, że zmieniłeś zdanie napisałeś w pierwszej wiadomości cytuje "za pomocą zapytania nie tworząc funkcji" smile:):), ale OK Twój projekt tylko zyska jeśli wykorzystasz funkcje.

5

Odp: Zapytanie zamiast funkcji