PDA

Zobacz pełną wersję : Sumowanie wartości kolumn z różnych tabel przy pomocy mechanizmu JDatabase



buttman
07-02-2018, 23:54
Cześć,

od pewnego czasu korzystam z Fabrika. Świetne narzędzie, przy jego pomocy tworzę rozmaite listy i zestawienia. Ponieważ ich prezentacja przez mechanizmy Fabrika jest dość uboga, postanowiłem samemu tworzyć zestawienia (dzięki Sourcererowi) z użyciem joomlowego mechanizmy JDatabase. Wszystko szło mi świetnie, zrobiłem do tej pory masę raportów, aż nagle potknąłem się na problemie, o którym w życiu bym nie pomyślał, że będzie taką zagwozdką.

Załóżmy, że mam trzy proste tabele (tabela1, tabela2, tabela3) o identycznej budowie - każda posiada kolumny: 'ID', 'data', 'tytul', 'udostepnianie'. W tych tabelach odnotowywane są statystyki udostępnień bibliotecznych czasopism (czyli jakiego dnia, jaki tytuł i ile razy udostępniono). Podsumowanie liczby wypożyczeń dla każdej z tabel z osobna (każda tabela reprezentuje inną agendę) to żaden problem. Problemem za to (przynajmniej dla mnie) jest zsumowanie w jednej tabeli liczby wszystkich udostępnień z wszystkich tabel.

Naprawdę siedzę nad tym i siedzę i nie chce mi to zadziałać. Na wszystkie sposoby starałem się zmusić do pracy 'unionAll' (zgodnie z dokumentacją (https://docs.joomla.org/Using_the_union_methods_in_database_queries)), żeby połączyć wszystkie tabele i je zsumować, ale za każdym razem fiasko - najczęściej otrzymuję komunikat 'Call to a member function select() on null'.

Może mi ktoś wskazać, co jest nie tak z tym zapytaniem?

$query = $db->getQuery(true);
$q2->select('data, sum(udostepnianie) as sumtab');
$q2->from('tabela2');
$q2->where($db->quoteName('data').'LIKE \'2015%\'');
$q3->select('data, sum(udostepnianie) as sumtab');
$q3->from('tabela3');
$q3->where($db->quoteName('data').'LIKE \'2015%\'');
$query->select('data, sum(udostepnianie) as sumtab');
$query->from('tabela1');
$query->where($db->quoteName('data').'LIKE \'2015%\'');
$query->unionAll($q2);
$query->unionAll($q3);
$query->group('substr(data,1,4)');
$db->setQuery($query);
$result = $db->loadObjectList();

Na wszelki wypadek zaznaczam, że żaden ze mnie orzeł bazodanowy.

Z góry dziękuję za pomoc

buttman
08-02-2018, 09:23
Uff, udało mi się rozwiązać problem (podejrzałem w pliku /administrator/components/com_finder/helpers/indexer/query.php. Działające zapytanie ma postać:

$query = $db->getQuery(true);
$query->select('data, sum(udostepnianie) as sumtab');
$query->from('tabela1');
$query->where($db->quoteName('data').'LIKE \'2015%\'');
$sub = clone $query;
$sub->clear('from');
$sub->from('tabela2');
$sub2 = clone $query;
$sub2->clear('from');
$sub2->from('tabela3');
$query->union($sub);
$query->union($sub2);
$db->setQuery($query);
$result = $db->loadObjectList();

Rozwiązanie nie jest doskonałe, bo dla każdej ze składowych tabel generuje osobną sumę, więc jest tyle zwróconych wartości, ile tabel. Sumowania tych wartości dokonałem już w PHP na poziomie tabeli z prezentacją wyników. Grunt, że działa. Jeśli ktoś zna bardziej eleganckie rozwiązanie tego problemu, to może się podzieli?...

buttman
08-02-2018, 11:25
Update! Dopracowałem zapytanie i teraz ładnie czesze wszystkie 3 tabele i zwraca jedną wartość (sumę):

$query1 = $db->getQuery(true)->select('*')->from('tabela1')->where($db->quoteName('data').'LIKE \'2015%\'');
$query2 = $db->getQuery(true)->select('*')->from('tabela2')->where($db->quoteName('data').'LIKE \'2015%\'');
$query3 = $db->getQuery(true)->select('*')->from('tabela3')->where($db->quoteName('data').'LIKE \'2015%\'');
$query = $db->getQuery(true)->select('data, sum(case when substr(data,1,4)=\'2015\' then udostepnienia else null end) as sumtab')->from('(' . $query1->union($query2)->union($query3) . ') tx');
$db->setQuery($query);
$result = $db->loadObjectList();

Warunek w 'select' wziął się stąd, że docelowe zapytanie będzie obejmowało podział udostępnień na przestrzeni kilku lat.

Może się to wszystko komuś jeszcze kiedyś przyda :-)