Paweł Ługowski

Paweł Ługowski Software Developer

Temat: Mam problem i szukam pomocy...

Witam, mam problem ze skonstuowaniem zapytania do MySQLa, więcej pod tym linkiem. Jakby ktoś miał jakieś zastrzeżenia do mojej chaotycznej wypowiedzi, proszę zapytać.

http://forum.php.pl/Zapytanie_do_mysql_porownanie_z_ta...

Pozdrawiam,
Paweł
Bartosz Ślepowronski

Bartosz Ślepowronski Problem? Jaki
problem?

Temat: Mam problem i szukam pomocy...

Po pierwsze, rozbij to na trzy tabele, salatki, skladnik, i Xref (IDsalatki, IDskladnika).

Po drugie, uzyj IN i NOT IN.

Po trzecie zrzuc array ze skladnikami do stringa w formacie '[1],[2],[3]..'

SQL do tego zapytania bedzie wygladac mniej wiecej tak:

SELECT distinct salatkaid FROM xref
WHERE skladnikid IN ($skladniki)
AND salatkaid NOT IN
(SELECT distinct salatkaid FROM xref
WHERE skladnikid NOT IN ($skladniki))

Bierzesz wszystkie salatki w ktorych zgadza sie przynajmniej jeden skladnik i wyrzucasz te w ktorych nie zgadza sie przynajmniej jeden.

Niech mnie ktos poprawi jesli cos pokrecilem.
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: Mam problem i szukam pomocy...

Fantastyczny przykład do czego prowadzi brak normalizacji...

Zakładając strukturę choć nieco bardziej znormalizowaną (czyli id, nazwa_sałatki, składnik) gdzie PK (id, składnik) (składnik to pewnie id to słownika składników), tabelę lodówka (składnik) - napisałoby się

select z.nazwa_sałatki
from sałatki z
left outer join lodówka l on z.składnik = l.składnik
group by z.nazwa_sałatki
having sum(case when l.składnik is null then 1 else 0 end) = 0

żeby dostać listę sałatek które możemy przygotować z tego, co mamy w lodówce.

Wracając do problemu...Najlepiej jakbyś przeprojektował bazę. W drugiej kolejności, normalizował w locie. W trzeciej

select z.nazwa_sałatki
from sałatki z
cross join lodówka l
where ',' || z.przepis || ',' like '%,' || l.składnik || ',%'
group by z.nazwa_sałatki
having count(*) = max(length(replace(z.przepis, ',', ''))) + 1

Innymi słowy, produkujesz iloczyn kartezjański z przepisów i składników, po czym bierzesz tylko takie, które są na liście. Do tego wiesz ile powinienneś składników zużyć (ilość przecinków + 1), tak więc wiesz ile w każdym przepisie powinno być użytych składników...Grzegorz G. edytował(a) ten post dnia 26.08.08 o godzinie 15:55
Igor Piotr I.

Igor Piotr I. IT manager/Senior
Oracle Developer

Temat: Mam problem i szukam pomocy...

jeszcze można by zrobić kombinacje wszystkich możliwości z tablicy 1 i porównywać z wartościami tablicy 2.

nie mówię że to dobry pomysł :) ale zadziałało by.Igor Piotr Idzior edytował(a) ten post dnia 26.08.08 o godzinie 18:58
Paweł Ługowski

Paweł Ługowski Software Developer

Temat: Mam problem i szukam pomocy...

Heh, zawsze próbowałem tworzyć bazy danych tak, aby jak najmniej tabel w to mieszać, widać cały czas byłem w błędzie. A czy może ktoś mnie uświadomić po co tworzyć tabele z relacją id_salatki , id_skladnika, skoro w tabeli skladniki, jaki id moge użyć właśnie id_salatki i mam o jedna tabele mniej...

Po trzecie zrzuc array ze skladnikami do stringa w formacie '[1],[2],[3]..'

Czy kolejność stringow ma znaczenie?

Grzegorz, mógłbyś mi troszeczkę rozjaśnić pojęcie "normalizował w locie" bo jakoś nie idzie mi kojarzenie faktów dzisiaj...

Pozdr,

konto usunięte

Temat: Mam problem i szukam pomocy...

Paweł Ługowski:
skladniki, jaki id moge użyć właśnie id_salatki i mam o jedna tabele mniej...

w takiej tabeli nie będziesz miał elementu jednoznacznie wskazującego dany rekord (w jednej sałatce jest wiele składników - więc id sałatki jako id składnika to nie jest chyba dobry pomysł)Michał Cieciński edytował(a) ten post dnia 26.08.08 o godzinie 19:05
Paweł Ługowski

Paweł Ługowski Software Developer

Temat: Mam problem i szukam pomocy...

Teraz zgłupiałem. Może ktoś rozrysować mi struktury tabel?
Grzegorz G.:
Wracając do problemu...Najlepiej jakbyś przeprojektował bazę. W drugiej kolejności, normalizował w locie. W trzeciej

select z.nazwa_sałatki
from sałatki z
cross join lodówka l
where ',' || z.przepis || ',' like '%,' || l.składnik || ',%'
group by z.nazwa_sałatki
having count(*) = max(length(replace(z.przepis, ',', ''))) + 1

Innymi słowy, produkujesz iloczyn kartezjański z przepisów i składników, po czym bierzesz tylko takie, które są na liście.

A co do tego.
Do tego wiesz ile powinienneś składników zużyć (ilość przecinków + 1), tak więc wiesz ile w każdym przepisie powinno być użytych składników...

Czy to oznacza, że np moge wyświetlić informację o tym, że sałatka wymaga np 4 skłądników z 20, które mam w lodówce?

(jeszcze kilka postów, i baze danych nazwe lodówka, tabele skladniki i zleceniodawca sie zdziwi skąd kopiowałem skrypt) :D
Bartosz Ślepowronski

Bartosz Ślepowronski Problem? Jaki
problem?

Temat: Mam problem i szukam pomocy...

Paweł Ługowski:
Po trzecie zrzuc array ze skladnikami do stringa w formacie '[1],[2],[3]..'

Czy kolejność stringow ma znaczenie?

Zadnego, [1] [2] [3] oznacza po prostu kolejne wartosci z array, jak chesz to mozesz je wrzucic do stringa w losowej kolejnosci :)

W kwesti projektowania baz, wygooglaj haslo "normalizacja danych" i poczytaj.

Mozesz zaczac od tego:
http://support.microsoft.com/kb/283878/pl
http://www.drivver.webpark.pl/nbd.htm
Paweł Ługowski

Paweł Ługowski Software Developer

Temat: Mam problem i szukam pomocy...

Ok, podążając Twoim przykłądem i przykładami normalizacji rozumiem, że tabele powinny wyglądać mniej więcej tak:

skladnik:
id | skladnik
1 | cebula
2 | kukurydza
3 | mieta
4 | chmiel

salatki:
id | nazwa
1 | cebul_kuk (cebula, kukurydza)
2 | ceb_chmiel (cebula, chmiel)
itd...

Xref:
salatka | skladnik
1 | 1
1 | 2
2 | 1
2 | 4
itd.

Dobrze rozumiem?

konto usunięte

Temat: Mam problem i szukam pomocy...

Dobrze rozumiem?
tak
Paweł Ługowski

Paweł Ługowski Software Developer

Temat: Mam problem i szukam pomocy...

ok, a teraz co gdyby (o czyms mi sie przypomnialo) do skladnikow dodac jeszcze jego typ... jakby to opisac... O typ np.

id | skladnik | typ
1 | wołowina | mieso
2 | marchew | warzywo
3 | jablko | owoc

stworzyc podobna baze do xref?

O i jeszcze wazna rzecz. Ilosc skladnika. Czy w xrefie moge utworzyć sobie kolejną kolumne nazwać ilosc i tam wpisywać np. 1kg, 2 lyżki itp? Czy to już jest sprzeczne z normalizacją?

A jak teraz sprawdzić dane przy wprowadzaniu. O tyle, o ile przy wczesniejszej tabeli sprawdzalem, czy salatka o nazwie juz jest i czy posiada skladniki to tutaj musze pewnie skakac od tabelki do tabelki i najpierw sprawdzić czy salatka jest, potem, jakie ma id, zobaczyc w xrefie jakie skladniki sa do niej przypisane i na koniec wywalic te skladniki, tak? Jak wychwycić duble wpisów?

btw. jak zdefiniować PK w Xref?Paweł Ługowski edytował(a) ten post dnia 26.08.08 o godzinie 21:35
Bartosz Ślepowronski

Bartosz Ślepowronski Problem? Jaki
problem?

Temat: Mam problem i szukam pomocy...

Paweł Ługowski:
ok, a teraz co gdyby (o czyms mi sie przypomnialo) do skladnikow dodac jeszcze jego typ... jakby to opisac... O typ np.

id | skladnik | typ
1 | wołowina | mieso
2 | marchew | warzywo
3 | jablko | owoc
stworzyc podobna baze do xref?

Do tego nie musisz, bo kazdy skladnik bedzie opisany tylko jednym typem. Mozesz za to wyciagnac opis typu do innej tabeli a do tej wstawiac same ID, ale to juz taka sztuka dla sztuki. Przynajmniej dopoki nie zamierzasz budowac w ten sposob jakiejs bazy produkcyjnej :)
O i jeszcze wazna rzecz. Ilosc skladnika. Czy w xrefie moge utworzyć sobie kolejną kolumne nazwać ilosc i tam wpisywać np. 1kg, 2 lyżki itp? Czy to już jest sprzeczne z normalizacją?

W zasadzie nie jest sprzeczne, w koncu xref mowi o tym jak sie maja jedne wartosci do drugich :)
A jak teraz sprawdzić dane przy wprowadzaniu. O tyle, o ile przy wczesniejszej tabeli sprawdzalem, czy salatka o nazwie juz jest i czy posiada skladniki to tutaj musze pewnie skakac od tabelki do tabelki i najpierw sprawdzić czy salatka jest, potem, jakie ma id, zobaczyc w xrefie jakie skladniki sa do niej przypisane i na koniec wywalic te skladniki, tak?

Na tym polegaja relacyjne bazy danych, tak z grubsza :P
Jak wychwycić duble wpisów?

Zalozyc PK?
btw. jak zdefiniować PK w Xref?

Na na obu FK najlepiej :)
Paweł Ługowski

Paweł Ługowski Software Developer

Temat: Mam problem i szukam pomocy...

Na tym polegaja relacyjne bazy danych, tak z grubsza :P

No racja <debil>

Ok, póki co informacje tu udzielone wystarczają mi... Jakby co to zapukam ponownie o pomoc. Wielgachne dzięki towarzysze!
Paweł Ługowski

Paweł Ługowski Software Developer

Temat: Mam problem i szukam pomocy...

Grzegorz G.:
select z.nazwa_sałatki
from sałatki z
left outer join lodówka l on z.składnik = l.składnik
group by z.nazwa_sałatki
having sum(case when l.składnik is null then 1 else 0 end) = 0
select z.nazwa_sałatki
from sałatki z
cross join lodówka l
where ',' || z.przepis || ',' like '%,' || l.składnik || ',%'
group by z.nazwa_sałatki
having count(*) = max(length(replace(z.przepis, ',', ''))) + 1

Cholera przerobiłem już wszystkie tabele tak, aby były nabardziej znormalizowane ale jakoś Twoje przykłądy nie chcą działać. Mógłbyś napisać je tak, żeby współgrały z nazwami tabel jakie używam?

czyli.

Mam 3 tabelki:

#1 salatki [s_id | s_name]
#2 components [c_id | c_name]
#3 xref [id_sal | id_comp]

I dane oczywiście wywalone w tablicy, ale tak jak Bartosz pisał są zimplodowane > implode(",",$_POST['co_mam']) do postaci po przecinkach... A i w tej tablicy wysyłam tylko id poszczególnych składników, mniejsza ilość danych do wysłania :D

Kurcze tak to jest jak cały czas używało się tylko najprostszych zapytań do mysqla, a potem trzeba nadrabiać zaległości :DPaweł Ługowski edytował(a) ten post dnia 29.08.08 o godzinie 15:27

Następna dyskusja:

Mam problem - ACCES




Wyślij zaproszenie do