Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: zliczanie ilość produktów w danej kategorii
Forum PHP.pl > Forum > Bazy danych > MySQL
DeyV
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 winksmiley.jpg byłoby otrzymać wynik w postaci:

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 winksmiley.jpg
dragossani
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.
uboottd
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 )
adwol
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]
DeyV
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 :/
adwol
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:
DeyV
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? winksmiley.jpg
adwol
Cytat
Mogę więc prosić o objaśnienie? winksmiley.jpg

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.
dragossani
Jestem pod wrażeniem tej agregacji po IF'ach. Niezłe. smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.