![]() |
![]() |
![]()
Post
#1
|
|
![]() Grupa: Zarząd Postów: 2 277 Pomógł: 6 Dołączył: 27.12.2002 Skąd: Wołów/Wrocław ![]() |
Hej.
zastanawaiłęm sie, czy nie dać jakiegoś mądrzejeszgo tematu, ale chyba taki jest najbardziej obrazowy. Akcja toczy się na MySQL, gdzie mamy 2 tabele, produkty i kategorie. Każdy produkt, poza id i nazwą, ma informacje o tym, do jakiej kategorii należy, oraz 1 pole dodatkowe - flagę, mogąć przyjmować wartość 0 lub 1. Zadanie polega na tym, by wyświetlić listę kategorii, wraz z 2 liczbami dotyczącymi ilości produktów należących do tej kategorii, osobno jednak licząc produkty o fladze 0, a osobno - 1. Przykład struktury bazy: Kod # Struktura tabeli dla `kategorie`
CREATE TABLE kategorie ( id int(11) NOT NULL auto_increment, nazwa varchar(100) NOT NULL default '', PRIMARY KEY (id) ) TYPE=MyISAM; # Zrzut danych tabeli `kategorie` INSERT INTO kategorie VALUES (1, 'kategoria 1'); INSERT INTO kategorie VALUES (2, 'kategoria 2'); INSERT INTO kategorie VALUES (3, 'kategoria 3'); # -------------------------------------------------------- # Struktura tabeli dla `produkty` CREATE TABLE produkty ( id int(11) NOT NULL auto_increment, nazwa varchar(100) NOT NULL default '', kat_id int(11) NOT NULL default '0', flaga tinyint(4) NOT NULL default '0', PRIMARY KEY (id), KEY kat_id (kat_id,flaga) ) TYPE=MyISAM; # Zrzut danych tabeli `produkty` INSERT INTO produkty VALUES (1, 'produkt 1', 1, 0); INSERT INTO produkty VALUES (2, 'produkt 2', 1, 0); INSERT INTO produkty VALUES (3, 'produkt 3', 1, 1); INSERT INTO produkty VALUES (4, 'produkt 4', 2, 0); Moim marzeniem ![]() Kod |id | nazwa | produkt_flag_0 | produkt_flag_1 |
|---+---------------+-------------------+------------------| | 1 | kategoria 1 | 2 | 1 | |---+---------------+-------------------+------------------| | 2 | kategoria 2 | 1 | 0 | |---+---------------+-------------------+------------------| | 3 | kategoria 3 | 0 | 0 | ------------------------------------------------------------ W pierwszej chwili zadanie wydaje się banalne. Ale ... chyba takie nie jest. A zresztą przekonajcie sie sami ![]() -------------------- "Niezależnie od tego, jakie masz osiągnięcia, ktoś Ci pomaga..."
|
|
|
![]() |
![]()
Post
#2
|
|
![]() Grupa: Przyjaciele php.pl Postów: 398 Pomógł: 0 Dołączył: -- Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Nie jest banalne bo wymaga rozgałęzienia agregacji, tzn. dwóch złączeń typu LEFT JOIN do tej samej tabeli, dwóch osobnych poleceń COUNT z osobnymi warunkami (WHERE dotyczący flagi). Jeśli ma być to zrobione w jednym zapytaniu - wymaga mechanizmu subqueries.
-------------------- cease this long, long rest / wake and risk a foul weakness to live / when it all comes down / watch the smoke and bury the past again / sit and think what will come / raise your fears and cast them all away
|
|
|
![]()
Post
#3
|
|
![]() Grupa: Zarejestrowani Postów: 384 Pomógł: 0 Dołączył: 3.04.2003 Skąd: Chorzow Ostrzeżenie: (0%) ![]() ![]() |
BANAL!!
[sql:1:e88c7ba0a7] SELECT kategorie.id, kategorie.nazwa, SUM(if(flag=0,1,0)) as produkt_flag_0, SUM(if(flag=1,1,0)) as produkt_flag_1 FROM kategorie LEFT JOIN produkty ON kat_id = kategorie.id GROUP BY kategorie.id; [/sql:1:e88c7ba0a7] IF jest tu uzyty tylko dla ilustracji jesli pole flag mogloby przyjmowac dowolne wartosci, jeszcze prostsza wersje dla podanych warunkow zadania zaraz zapoda adwol. Lub dla ciekawosci na dwoch sklejeniach: [sql:1:e88c7ba0a7] SELECT kategorie.id, kategorie.nazwa, SUM(if(p1.flag=0,1,0)) as produkt_flag_0, SUM(ifnull(p2.flag,0)) as produkt_flag_1 FROM kategorie LEFT JOIN produkty as p1 ON p1.kat_id = kategorie.id AND flag = 0 LEFT JOIN produkty as p2 ON p2.kat_id = kategorie.id AND flag = 1 GROUP BY kategorie.id; [/sql:1:e88c7ba0a7] Jak na razie spotkalem dokladnie jedna bardzo zagrzybiona sytuacje gdzie nie jestem do konca pewien czy uda sie to zrobic jednym zapytaniem bez podzapytan (dalem to zadanie w http://forum.php.pl/viewtopic.php?t=2093 ) |
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 691 Pomógł: 0 Dołączył: 6.08.2003 Ostrzeżenie: (0%) ![]() ![]() |
Cytat Hej.
zastanawaiłęm sie, czy nie dać jakiegoś mądrzejeszgo tematu, ale chyba taki jest najbardziej obrazowy. Akcja toczy się na MySQL, gdzie mamy 2 tabele, produkty i kategorie. Każdy produkt, poza id i nazwą, ma informacje o tym, do jakiej kategorii należy, oraz 1 pole dodatkowe - flagę, mogąć przyjmować wartość 0 lub 1. Zadanie polega na tym, by wyświetlić listę kategorii, wraz z 2 liczbami dotyczącymi ilości produktów należących do tej kategorii, osobno jednak licząc produkty o fladze 0, a osobno - 1. [sql:1:7c3dd86fdb]select kategorie.nazwa, ifnull(sum(1-produkty.flaga),0) as produkt_flag_0, ifnull(sum(produkty.flaga),0) as produkt_flag_1 from kategorie left join produkty on kat_id=kategorie.id group by kategorie.id; [/sql:1:7c3dd86fdb] |
|
|
![]()
Post
#5
|
|
![]() Grupa: Zarząd Postów: 2 277 Pomógł: 6 Dołączył: 27.12.2002 Skąd: Wołów/Wrocław ![]() |
Cytat jeszcze prostsza wersje dla podanych warunkow zadania zaraz zapoda adwol.
Prorok, czy co? ;:) A na powaźnie - dzięki, (i widać z tego, że o SQL jest znacznie potęzniejszy, niż się zazwyczaj wydaje) Choć nie rozumiem, po co w warunku adwola jest sprawdzanie IFNULL :/ -------------------- "Niezależnie od tego, jakie masz osiągnięcia, ktoś Ci pomaga..."
|
|
|
![]()
Post
#6
|
|
![]() Grupa: Zarejestrowani Postów: 691 Pomógł: 0 Dołączył: 6.08.2003 Ostrzeżenie: (0%) ![]() ![]() |
Cytat Choć nie rozumiem, po co w warunku adwola jest sprawdzanie IFNULL :/
Usuń to i sprawdź na danych które podałeś to się dowiesz. :wink: |
|
|
![]()
Post
#7
|
|
![]() Grupa: Zarząd Postów: 2 277 Pomógł: 6 Dołączył: 27.12.2002 Skąd: Wołów/Wrocław ![]() |
Cytat Usuń to i sprawdź na danych które podałeś to się dowiesz. :wink:
Zapytanie Kod SELECT kategorie.nazwa,
sum( 1 - produkty.flaga ) AS produkt_flag_0, sum( produkty.flaga ) AS produkt_flag_1 FROM kategorie LEFT JOIN produkty ON kat_id = kategorie.id GROUP BY kategorie.id daje dokładnie to samo (przynajmniej na tych danych) Mogę więc prosić o objaśnienie? ![]() -------------------- "Niezależnie od tego, jakie masz osiągnięcia, ktoś Ci pomaga..."
|
|
|
![]()
Post
#8
|
|
![]() Grupa: Zarejestrowani Postów: 691 Pomógł: 0 Dołączył: 6.08.2003 Ostrzeżenie: (0%) ![]() ![]() |
Cytat Mogę więc prosić o objaśnienie?
![]() Dla tych danych które podałeś: Kod mysql> select kategorie.nazwa, sum(1-produkty.flaga) as produkt_flag_0, sum(prod
ukty.flaga) as produkt_flag_1 from kategorie left join produkty on kat_id=katego rie.id group by kategorie.id; +-------------+----------------+----------------+ | nazwa | produkt_flag_0 | produkt_flag_1 | +-------------+----------------+----------------+ | kategoria 1 | 2 | 1 | | kategoria 2 | 1 | 0 | | kategoria 3 | NULL | NULL | +-------------+----------------+----------------+ Kod mysql> select kategorie.nazwa, ifnull(sum(1-produkty.flaga),0) as produkt_flag_0
, ifnull(sum(produkty.flaga),0) as produkt_flag_1 from kategorie left join produ kty on kat_id=kategorie.id group by kategorie.id; +-------------+----------------+----------------+ | nazwa | produkt_flag_0 | produkt_flag_1 | +-------------+----------------+----------------+ | kategoria 1 | 2 | 1 | | kategoria 2 | 1 | 0 | | kategoria 3 | 0 | 0 | +-------------+----------------+----------------+ Po prostu left join spowoduje że puste kategorie będą miały nulle zamiast zer, a z tego co widziałem to chciałeś zera. W phpie po wyciągnięciu wyników takiego zapytania w miejsce nulla dostaniesz ciąg pusty co może mieć znaczenie. |
|
|
![]()
Post
#9
|
|
![]() Grupa: Przyjaciele php.pl Postów: 398 Pomógł: 0 Dołączył: -- Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Jestem pod wrażeniem tej agregacji po IF'ach. Niezłe.
![]() -------------------- cease this long, long rest / wake and risk a foul weakness to live / when it all comes down / watch the smoke and bury the past again / sit and think what will come / raise your fears and cast them all away
|
|
|
![]() ![]() |
![]() |
Aktualny czas: 21.08.2025 - 07:37 |