Skomplikowane zapytanie do bazy.

0

Witam.
Posiadam bazę danych która ma następujący format.

Typ Wersja Kolor Status Typdefektu Data&godzina Ilość
Typ1 Wersja1 Czarny OK NULL 2013-01-22 1532 1
Typ1 Wersja1 Bialy NOK Defekt1 2013-01-22 1520 50
Typ2 Wersja1 Czarny OK NULL 2013-01-22 1530 1
Typ3 Wersja1 Czerwony NOK Defekt2 2013-01-22 1530 1

Szukam prostego rozwiązania na skonstruowanie zapytania które zwróciło by mi dane (PHP) w formie:

| | Defekt1 | Defekt2 | Defekt3 | Defekt4
Typ1 | | 2 | 2 | 0 | 5
| Czarny | 1 | 2 | 0 | 4
| Czerwony | 1 | 0 | 0 | 1
Typ2 | | 2 | 3 | 3 | 4
| Bialy | 1 | 1 | 1 | 3
| Czarny | 1 | 2 | 2 | 1

Wartości liczbowe w wierszu "Typ" przedstawiają sumę takich defektów dla danego typu.
Wartości liczbowe w wierszu danego koloru przedstawiają sumę takich defektów dla kombinacji Typ->Kolor.
Na chwilę obecną nie mam żadnego pomysłu jak tylko wypytywać każdą kombinację Typ->Kolor->Defekt oddzielnie, jednak takie rozwiązanie jest czasochłonne i nie wydaje się najbardziej optymalne.
Do tej pory używałem Excela i VBA gdzie takie wartości można w łatwy sposób wyciągnąć za pomocą kilku formuł jednak w miarę rozrastania się ilości typów, kolorów etc. plik zaczął zajmować 15Mb. Praca na pliku, który znajduje się na dysku sieciowym jest coraz wolniejsza.
Dlatego postanowiłem coś napisać w PHP i postawić na serwerze aby przyspieszyć działanie systemu. Z dotychczasowych działań wynika że jest on jeszcze wolniejszy od Excela :)
Macie jakieś propozycje bardziej skondensowanego zapytania, które pozwoliło by mi zwrócić wyniki w postaci pokazanej powyżej?

Jeśli wyraziłem się nie jasno z moim pytanie proszę o pytania uzupełniające.

Pozdrawiam.

0

chcesz sam napisać zapytanie i żeby Ci napisać podpowiedzi czy wolisz gotowe zapytanie?

Tak, żeby nie było że mój post nic nie wnosi to na pewno proponował bym skorzystać z union, jako że tabela jest nieregularna

Interesuje nas tak naprawdę nazwijmy ją tabela1 (reszta to dla nas śmieci):

Typ Kolor Typ defektu Ilość
Typ1 Biały Defekt1 Ilość

Ja zaproponuje co ja bym zrobił:

  • kolory przeniósł bym do osobnej tabeli tu zostawiając tylko ID_koloru 1,2,3,4,10 itd... (chyba że są stałe i jest ich określona ilość, możesz wszystkie wymienić)
  • Typy jw bo przypuszaczam, ze też są niezbyt regularne... a musimy mieć przecież jakiś punkt odniesienia do pentli ;)
    i potem, pętla zliczająca

Pytanie - czy korzystamy z sql czy pl/sql (lepiej, łatwiej, szybciej)?

0

Bardzo dużo zależy od bazy na której pracujesz.
Ja najwięcej pracuję w Oracle i zaproponowałbym takie rozwiązanie:

  1. Wyznaczam wiersze, które mają typ i kolor
select 
  typ,
  kolor,
  sum (decode (typ_defektu, 'Defekt1', ilosc, 0)) Defekt1,
  sum (decode (typ_defektu, 'Defekt2', ilosc, 0)) Defekt2,
  sum (decode (typ_defektu, 'Defekt3', ilosc, 0)) Defekt3,
  sum (decode (typ_defektu, 'Defekt3', ilosc, 0)) Defekt4
 from moja_tabela
where status = 'NOK'
group by
 typ, kolor
 

Decode to taka odmiana IF'a. W tym przypadku czyta się to tak: Jeżeli pierwsza wartość równa się drugiej to bierzemy 'ilość' , w przeciwnym przypadku bierzemy 0.

  1. Wyznaczamy wiersze posiadające tylko typ (suma po typie, ignorujemy kolor).
select 
  typ,
  null kolor,
  sum (decode (typ_defektu, 'Defekt1', ilosc, 0)) Defekt1,
  sum (decode (typ_defektu, 'Defekt2', ilosc, 0)) Defekt2,
  sum (decode (typ_defektu, 'Defekt3', ilosc, 0)) Defekt3,
  sum (decode (typ_defektu, 'Defekt3', ilosc, 0)) Defekt4
 from moja_tabela
where status = 'NOK'
group by
 typ
 

Ważne! Dodajemy puste pole kolor (NULL as kolor, w Oracle wolno pominąć AS), aby można było bez problemu połączyć zapytanie 2 z zapytaniem 1 za pomocą UNION

  1. Łączymy oba zapytania i sortujemy po typ, kolor
select * from 
 (select 
   typ,
   kolor,
   sum (decode (typ_defektu, 'Defekt1', ilosc, 0)) Defekt1,
   sum (decode (typ_defektu, 'Defekt2', ilosc, 0)) Defekt2,
   sum (decode (typ_defektu, 'Defekt3', ilosc, 0)) Defekt3,
   sum (decode (typ_defektu, 'Defekt3', ilosc, 0)) Defekt4
   from moja_tabela
 where status = 'NOK'
 group by
  typ, kolor
 UNION ALL
  select 
   typ,
   null kolor,
   sum (decode (typ_defektu, 'Defekt1', ilosc, 0)) Defekt1,
   sum (decode (typ_defektu, 'Defekt2', ilosc, 0)) Defekt2,
   sum (decode (typ_defektu, 'Defekt3', ilosc, 0)) Defekt3,
   sum (decode (typ_defektu, 'Defekt3', ilosc, 0)) Defekt4
  from moja_tabela
 where status = 'NOK'
 group by
    typ)
Order by typ, kolor

Uwagi:
a) Składnia ORACLE. W przypadku innych systemów zarządzania bazą danych (SZBD) należy znaleźć odpowiednik DECODE (w MS SQL: CASE when typ_defectu='Defekt1' THEN ilosc else 0).
b) prawdopodobnie nie ma potrzeby zastosowania select * from ( .. Union all ...) order by. W Oracle wystarczyłoby napisać po ostatnim składniku unii ORDER BY 1,2 - ale wtedy jest niska czytelność kodu, a nie jestem pewien czy inne SZBD coś takiego obsłużą - dlatego zdecydowałem się na select z ( zapytanie1 UNION zapytanie2)

1 użytkowników online, w tym zalogowanych: 0, gości: 1