SQL - obliczanie minimum z podaniem detali
Marek - 12-11-2006 01:33
SQL - obliczanie minimum z podaniem detali
Witam,
Chyba mam zaćmę umysłową - problem jest banalny: jak wyznaczyć wartość minimalną takiego układu tabel:
create table lista ( lista_id primary key,
nazwa text );
create table pole_listy ( pole_listy_id primary key, lista_id foreign key references lista (lista_id),
nazwa_pola text );
create table wartosc_pola ( wartosc_pola_id primary key, pole_listy_id foreign key references pole_listy (pole_listy_id), dokument_id foreign key references document (document_id),
wartosc float, inne_pole, .... );
Chcę wyznaczyć najmniejszą wartość pola "wartosc" w tabeli wartosc_pola dla każdego dokumentu i podać wszystkie detale tabeli pole_listy i lista. Kombinowałem tak:
SELECT min(wp.wartosc), pl.*, l.*, (SELECT ... FROM xx WHERE ...tutaj jakieś pole z tabeli wp) AS utrudnienie. FROM wartosc_pola wp, pole_listy pl, lista l WHERE wp.pole_listy_id=pl.pole_listy_id AND pl.lista_id=l.lista.id GROUP BY wp.document_id
Oczywiście baza żąda podania w group by wszystkich pól wszyskich tabel. Sęk w tym, że nie mogę tam przecież wstawić pola "utrudnienie" a także niekoniecznie chciałbym przytaczać w klauzuli group by mnóstwo pól ze wszystkich stosowanych tabel. Czy da się to rozwiązać bez robienia do tego procedury programowej, która najpierw wyznaczyłaby pary (min(wp.wartosc),wartosc_pola_id) a potem dla każdego rekordu tworzyłaby w pętli zapytania do bazy o detale dla każdego wartosc_pola_id ? Chciałbym wykonać operację w jednym zapytaniu SQL bo w przeciwnym razie powstanie z tego parę tysięcy zapytań skierowanych do bazy, co byłoby chorym rozwiązaniem.
Pozdrawiam, Marek
Marcin A. Guzowski - 12-11-2006 01:33
Marek napisał(a): > Witam, > > Chyba mam zaćmę umysłową - problem jest banalny: jak wyznaczyć wartość > minimalną takiego układu tabel: >(..) > Oczywiście baza żąda podania w group by wszystkich pól wszyskich tabel. > Sęk w tym, że nie mogę tam przecież wstawić pola "utrudnienie" a także > niekoniecznie chciałbym przytaczać w klauzuli group by mnóstwo pól ze > wszystkich stosowanych tabel.
Gwarantuję Ci, że przy wypisaniu w GROUP BY wszystkich kolumn wynik nie byłby zgodny z Twoimi oczekiwaniami.
> Czy da się to rozwiązać bez robienia do > tego procedury programowej, która najpierw wyznaczyłaby pary > (min(wp.wartosc),wartosc_pola_id) a potem dla każdego rekordu tworzyłaby > w pętli zapytania do bazy o detale dla każdego wartosc_pola_id ?
Jej, nie strasz - oczywiście, że się da. Baza chce mieć pełne pokrycie kolumn w GROUP BY, bo i wszystkie kolumny klauzulą GROUP BY objąłeś. Rozwiązaniem jest tutaj odpowiedni join kilku tabel i podzapytania z GROUP BY, gdzie grupowane jest tylko to, co powinno. Mam na myśli coś takiego:
SELECT * FROM ( SELECT pole_listy_id, min(wartosc) as min_wartosc FROM wartosc_pola GROUP BY pole_listy_id ) wp INNER JOIN pole_listy pl --(a może inny join - zależy co chcesz osiągnąć) ON (wp.pole_listy_id = pl.pole_listy_id) INNER JOIN lista l ON (pl.lista_id = l.lista_id) (..)
Pisałem dość swobodnie, a i Ty nie podałeś specyfikacji wszystkich tabel (np. tabeli document, zrobiłem więc pewnie nieco inne grupowanie) - będziesz musiał dostosować zapytanie do swoich potrzeb. Ale mam nadzieję, że ideę widać.
-- Pozdrawiam, Marcin Guzowski http://guzowski.info
Marek - 12-11-2006 01:33
> Gwarantuję Ci, że przy wypisaniu w GROUP BY wszystkich kolumn > wynik nie byłby zgodny z Twoimi oczekiwaniami.
Hmmm ... jest tylko małe "ale": niektóre kolumny w tabeli tworzone są dynamicznie i w związku z tym trudno mi jest określić jakie z nich będą występowały. Dlatego notacja gwiazdkowa byłaby dla mnie idealna, a skoro nie funkcjonuje, to stąd moje pytanie o alternatywę.Ponadto - już abstrachując od wątku - nie jestem przekonany czy grupowanie po kolumnie zawierającej np. 20kB tekstu jest rozsądne z punktu widzenia optymalizacji.Dlatego m.in. upodobałem sobie pojedynczą kolumnę.
> Jej, nie strasz - oczywiście, że się da.
Sam się przestraszyłem :-))) Dlatego tu napisałem aby unicestwić moje lęki :-))))
> Baza chce mieć pełne pokrycie kolumn w GROUP BY, bo i wszystkie kolumny > klauzulą GROUP BY objąłeś. Rozwiązaniem jest tutaj odpowiedni join kilku > tabel i podzapytania z GROUP BY, gdzie grupowane jest tylko to, co > powinno. > Mam na myśli coś takiego:
A to rewelka! No tak, nie pomyślałem o joinowaniu podzapytania. Zaraz to przetrenuję.
> Pisałem dość swobodnie, a i Ty nie podałeś specyfikacji wszystkich tabel > (np. tabeli document, zrobiłem więc pewnie nieco inne grupowanie) - > będziesz musiał dostosować zapytanie do swoich potrzeb. Ale mam nadzieję, > że ideę widać.
Tak, bardzo dokładnie :) Dzięki! A co do tabeli document, to nie ma ona znaczenia gdyż nie potrzebuję z niej żadnych innych danych niż zwraca mi select. Dlatego nie rozwijałem wątku w tą stronę aby nie zaćmić problemu głównego.
Marek - 12-11-2006 01:33
Właśnie skończyłem pracę - udało się wykorzystać podzapytanie do JOINa skutecznie :-) Dzięki za pomoc!
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
jak to =?ISO-8859-2?Q?zrobi=E6=2E=2E=2E=3F_TSQL_sql_server?==?ISO-8859-2?Q?_?=
Jak =?windows-1250?Q?pobra=E6_szacowan=B9_wielko=9C=E6_zbiory_wy nikowego_w_MS?==?windows-1250?Q?_SQL_2005=3F?=
=?iso-8859-2?Q?=5BMS_SQL=5D_Czy_mo=BFna_wywo=B3a=E6_funkcje_t ylko_raz_dla?==?iso-8859-2?Q?_ca=B3ego_zbioru_=BCr=F3d=B3owego=3F?=
[MSSQL] =?ISO-8859-2?Q?zgodno=B6ci_z_licencjami_Microsoft_?==?ISO-8859-2?Q?SQL_Server?=
=?ISO-8859-2?Q?k=B3opot_z_uruchomieniem_MY_SQL_dla_C?==?ISO-8859-2?Q?MS_i_CRM_na_Fedora_Core_3?=
Oracle PL/SQL Wstawianie =?ISO-8859-2?Q?wynik=F3w_kolekcji_d?==?ISO-8859-2?Q?o_tabeli?=
[MSSQL] ACCESS - SQL =?ISO-8859-2?Q?B=B3ad_w_konwersji_lic?==?ISO-8859-2?Q?zb?=
=?iso-8859-2?Q?=5Bmssql=5D_Zapytania_rekurencyjne__-_czy_sk=B3adnia_sql?==?iso-8859-2?Q?_co=B6_takiego_przewiduje_=3F?=
[Oracle PL/SQL] Cursor i zapis =?ISO-8859-2?Q?rekord=F3w_do_?==?ISO-8859-2?Q?kolejnych_plik=F3w?=
=?iso-8859-2?Q?=5BMySQL=5D_Co_minimalnie_potrzebne_zeby_mie=E 6_klienta_My?==?iso-8859-2?Q?SQL_na_Linuxie=3F?=
zanotowane.pldoc.pisz.plpdf.pisz.plradioaktywni.htw.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|