Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Zapytanie do mysql - porównanie z tablicą., Tablica jako zapytanie typu SELECT * FROM WHERE x in_array...
exseerius
post
Post #1





Grupa: Zarejestrowani
Postów: 55
Pomógł: 0
Dołączył: 31.12.2006

Ostrzeżenie: (0%)
-----


Szukałem na forum, ale nawet nie wiem jak nazwać problem, toteż nowy temat:

Mam problem ze skonstruowaniem zapytania do mysql, które wyświetli mi rekordy zawierające dane należące do zbioru wejściowego.

Dla przykłady chodzi mi o coś takiego, co dla zbioru wejściowego - tablicy z danymi -

np.
Kod
Array {
    0 => 1;
    1 => 2;
    2 => 3;
    3 => 4;
    4 => 5
}


wyświetli rekordy, które w kolumnie 'wartości' posiada jeden lub wiecej z danych wejsciowych, ale pominie rekordy, w których znajdują się jeszcze inne, dodatkowe dane, np:

Kod
+----+-----------+
| id | wartości  |
+----+-----------+
| 1  | 1;2;5     | ok
+----+-----------+
| 2  | 1;4       | ok
+----+-----------+
| 3  | 1;2;3;4;5 | ok
+----+-----------+
| 4  | 1;2;6     | bad
+----+-----------+
| 5  | 7;8;10    | bad
+----+-----------+



Zapytanie "SELECT * WHERE `wartości` REGEXP "1" AND wartości REGEXP "2" itd " nie ma tu prawa bytu, bo to bedzie szukało tylko tych wierszy, które zawierają wszystkie dane. Czy da się to zrobić za pomocą jednego zapytania do mysql, które wywali gotowca, czy wymagana będzie jeszcze obróbka danych w PHP, za pomocą porównań i sprawdzeń np in_array? Dodam, że o ile dla 5 zapytań to jest stosunkowo lekkie i do przetrawienia, o tyle przy 150 może być pewnie problem.

Dodam, że skrypt będzie musiał wykonywać porównania dla dwóch kolumn... Tak jak teraz wartości porównać z tablicą spr_wartości i kolumnę wartości_2 porównać z tablicą spra_wartości_2 (zrozumiałe, czy może zamieszałem za bardzo?). A dane w bazie danych nie będą liczbami, a stringami...

W jakiej formie najlepiej przechowywać dane w bazie danych? Czy oddzielone od siebie średnikami wystarczy, czy może zastosować coś innego? Co radzicie, żeby skrypt był lekki i szybki w działaniu?

Dane wejściowe brane są z checkboxów, ale to chyba nie ma większego znaczenia (IMG:http://forum.php.pl/style_emoticons/default/biggrin.gif)

Pozdrawiam,
ex

ok, dla przykłądu jeszcze dodam, że zależałoby mi, aby skrypt działał na zasadzie tworzenia sałatki ze składników, które podał użytkownik. Np user podaje, że ma w lodówce:

Kod
Array {
  0 => pomidor,
  1 => ogórek,
  2 => sałata,
  3 => ananas,
  4 => cebula...
  ...
}


No i w bazie są np takie wpisy:

Kod
id    nazwa                  składniki
1    pomidorowo-ogórkowa    pomidor, ogórek
2    ziemniaczana           ziemniaki,cebula, kukurydza
3    dziwna                 cebula,ananas, sałata
4    odlotowa               zioło,haszysz, kokaina


I w takiej sytuacji wybiera rekordy 1 i 3, bo składniki, z których się składają zawierają się w zbiorze, który posiada pseudo kucharz.

Wiem, że jest tu ktoś na tyle mądry, kto poratuje w tej zamieszanej dla mnie sytuacji...

P.S. Autor nie zaleca testowania podanych w przykładzie sałatek!

Ten post edytował exseerius 26.08.2008, 10:35:56
Go to the top of the page
+Quote Post
SirZooro
post
Post #2





Grupa: Zarejestrowani
Postów: 243
Pomógł: 32
Dołączył: 14.06.2007

Ostrzeżenie: (0%)
-----


Bezpośrednio z zapytania będzie raczej ciężko. Masz w zasadzie dwa wyjścia:
- napisać procedurę składowaną (stored procedure) która pobierze dane z pola, rozbije je je na składowe, porówna z przekazanymi wartościami i zwróci wynik;
- przerobić schemat bazy danych tak aby mieć jedną tabelę z nazwami poszczególnych składników (tabela słownikowa) i drugą która będzie łączyć poszczególne przepisy z odpowiednimi składnikami. Wtedy napisanie odpowiedniego zapytania byłoby znacznie łatwiejsze.
Go to the top of the page
+Quote Post
exseerius
post
Post #3





Grupa: Zarejestrowani
Postów: 55
Pomógł: 0
Dołączył: 31.12.2006

Ostrzeżenie: (0%)
-----


ok, załóżmy, że wybieram opcję druga, tabelę słownikową, w której mam załóżmy:

id_salatki | skladnik_1 | skladnik_2 | skladnik_3 | itd

Jak teraz najlepszą (najoptymalniejszą metodą) wykonać zapytanie, bo nadal widzę tylko sprawdzanie każdego rekordu pod kątem:

in_array($_POST['co_mam'],skladnik_1)
in_array($_POST['co_mam'],skladnik_2)
in_array($_POST['co_mam'],skladnik_3) itd,

a to z kolei mija się z celem. Mogę też wywalić wszystkie rekordy, które mają przynajmniej jeden ze składników i później pętlą w pehapie sprawdzać po kolei, czy reszta skłądników również się zgadza, ale to z kolei już jest pamięciożerne przy wiekszej liczbie wpisów, a baza nie będzie wcale mała (użycie firmowe)...

Jakieś inne sugestie?
Go to the top of the page
+Quote Post
dymsza
post
Post #4





Grupa: Zarejestrowani
Postów: 62
Pomógł: 4
Dołączył: 24.08.2006

Ostrzeżenie: (0%)
-----


nie odpowiednio skontrolowałeś bazę powinieneś mieć jeszcze table składniki i tabele składnik_mtm czyli pośrednią tablice łączącą skłądniki z saładką

w ten sposób możesz zrobić tak

  1. SELECT s.id form saladki a s LEFT JOIN skladznik_mtm AS k ON k.id_saladki = s.id
  2.  
  3. WHERE k.id_skladnika IS NOT IN (' tu php : implode(','$tablica z numerami ) ')
  4.  
  5. GROUP BY s.id


wynikiem będą wszystkie id nie spełniające wymogów

jeśli chcesz teraz wyciągnąć takie co spełniają dajesz pod zapytanie i gra muzyka.

Ten post edytował dymsza 28.08.2008, 21:43:00
Go to the top of the page
+Quote Post
exseerius
post
Post #5





Grupa: Zarejestrowani
Postów: 55
Pomógł: 0
Dołączył: 31.12.2006

Ostrzeżenie: (0%)
-----


Ok, zmieniłem struktury tabel i mam teraz takie:

salatki:

id | s_name | recipe

components:

id | c_name

xref:

id_s | id_c | amount

Próbując zapytania:

  1. SELECT s.id form saladki a s LEFT JOIN xref AS k ON k.id_s = s.id
  2.  
  3. WHERE k.id_c IS NOT IN ('1,2,4,7,8')
  4.  
  5. GROUP BY s.id


paraser SQLa wywala mi błąd:

  1. Błąd
  2.  
  3. zapytanie SQL: Dokumentacja
  4.  
  5. SELECT s.id form salatki a s
  6. LEFT JOIN xref AS k ON k.id_c = s.id
  7. WHERE k.id_c IS NOT
  8. IN (
  9. '1,9,11,12'
  10. )
  11. GROUP BY s.id
  12.  
  13. MySQL zwrócił komunikat: Dokumentacja
  14. #1064 - Something is wrong in your syntax obok 'salatki a s left join xref as k on k.id_c = s.id
  15.  
  16. WHERE k.id' w linii 1


ktoś może powiedzieć co tu jest nie tak?
Go to the top of the page
+Quote Post
dymsza
post
Post #6





Grupa: Zarejestrowani
Postów: 62
Pomógł: 4
Dołączył: 24.08.2006

Ostrzeżenie: (0%)
-----


masz napisane a s zamiast AS mój błąd (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) ale trzeba uważać (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) bo napisałem to poglądowo a nie pod COPY&PASTE

Ten post edytował dymsza 29.08.2008, 20:28:48
Go to the top of the page
+Quote Post
exseerius
post
Post #7





Grupa: Zarejestrowani
Postów: 55
Pomógł: 0
Dołączył: 31.12.2006

Ostrzeżenie: (0%)
-----


Poprawiłem kilka literówek, ale nadal nic... :/
Go to the top of the page
+Quote Post
szopen
post
Post #8





Grupa: Zarejestrowani
Postów: 60
Pomógł: 5
Dołączył: 28.08.2008

Ostrzeżenie: (0%)
-----


Dane takie jak "1;2;3;4;5" nie mają racji bytu. Doprowadź swoją bazę do 3NF (albo przynajmniej 1NF) i problem się rozwiąże sam. A do tego najprawdopodobniej zyskasz na wydajności.

http://twity.republika.pl/download/bazy/sql_wyklad.pdf
http://en.wikipedia.org/wiki/Database_normalization
Go to the top of the page
+Quote Post
dymsza
post
Post #9





Grupa: Zarejestrowani
Postów: 62
Pomógł: 4
Dołączył: 24.08.2006

Ostrzeżenie: (0%)
-----


nie tu leży problem on po prostu zapisał '1,2,4,7,8' a powinno być 1,2,4,7,8 ewentualnie '1','2','4','7','8' (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

normalizacja bazy jest ok

to relacja table >> mtm << słownik
Go to the top of the page
+Quote Post
exseerius
post
Post #10





Grupa: Zarejestrowani
Postów: 55
Pomógł: 0
Dołączył: 31.12.2006

Ostrzeżenie: (0%)
-----


@szopen, jakbyś czytał cały wątek doczytałbyś, że już znormalizowałem tabele, w zapytaniu te liczby to id poszczególnych składników, które wysyłam postem w postaci tabliczy.

@dymsza, jak próbuję Twój sposób wrzucić w zapytanie (z którym wyżej miałem problem) to nadal jakiś błąd wyskakuje... Mógłbyś poprowadzić za rękę i pomóc stworzyć zapytanie dla tabel jak wyżej? Dziękować.

-- edit --
ok @dymsza - okazałeś się bardzo pomocny, masz plusa, ale jeszcze pytanie, czy da rade wywalić zapytanie, które da wyniki spełniające kryteria, a nie te, które nie spełniają go? Dla mnie to troche droga naokoło, żeby znaleźć, dajmy na to, kilkaset rekordów, które nie spełniają wymogów, żeby potem poszukać kolejne kilkaset, które też "not in"... dwa zapytania, zupełnie niepotrzebnie (IMG:http://forum.php.pl/style_emoticons/default/biggrin.gif)

Ten post edytował exseerius 1.09.2008, 17:39:47
Go to the top of the page
+Quote Post
szopen
post
Post #11





Grupa: Zarejestrowani
Postów: 60
Pomógł: 5
Dołączył: 28.08.2008

Ostrzeżenie: (0%)
-----


racja -- po zobaczeniu takiej struktury nie czytałem dalej...

nie wiem czy dokładnie o to Ci chodzi, ale popatrz sobie tu http://forum.php.pl/index.php?s=&showt...st&p=511757
czyli coś w stylu
  1. WHERE k.id_c IN (1,9,11,12) HAVING count(DISTINCT k.id_c)=4


Ten post edytował szopen 1.09.2008, 21:19:21
Go to the top of the page
+Quote Post
exseerius
post
Post #12





Grupa: Zarejestrowani
Postów: 55
Pomógł: 0
Dołączył: 31.12.2006

Ostrzeżenie: (0%)
-----


ok szopen, a powiedz teraz co tym osiągnę? Bo zapytanie już sobie skleciłem i działa znakomicie, ale... no właśnie wywala mi rekordy, które nie spełniają kryteriów, czyli które mają o jeden lub więcej składników za mało (trochę paradoksalnie brzmi (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif) ), rozumiem, że ta ostatnia liczba zależna jest od ilości danych wysłanych postem. Pytanie, czy to zadzaiałą tak jak chcę, żeby zadziałało?
Go to the top of the page
+Quote Post
szopen
post
Post #13





Grupa: Zarejestrowani
Postów: 60
Pomógł: 5
Dołączył: 28.08.2008

Ostrzeżenie: (0%)
-----


Nie wiem jak wygląda Twoje zapytanie. Nie wiem co masz w bazie. Tak, ostatnia liczba określa ilość składników. A jak chcesz aby zadziałało?
Cytat(szopen @ 31.08.2008, 20:43:27 ) *
a) dokładnie te atrakcje które podasz (nie mniej, nie więcej), b) te atrakcje które podasz i mogą być jeszcze jakieś, c) pokoje w których jest conajmniej jedna z podanych atrakcji?
Go to the top of the page
+Quote Post
exseerius
post
Post #14





Grupa: Zarejestrowani
Postów: 55
Pomógł: 0
Dołączył: 31.12.2006

Ostrzeżenie: (0%)
-----


D) tyle ile wybrałem atrakcji i\lub mniej (na pewno nie więcej).

Dla tego przykład z sałaytką dałem - w lodówce mam kilka składników a to jaka sałatka bedzie nie ma znaczenia, grunt, żey z tego co mam zrobić coś, a niekoniecznie trzeba użyć wszystko! I oczywiście wszystkie muszą być w jednym przepisie. Bo z tego co mi sie wydaje po wybraniu opcji <=4 wywali mi salatki, które mają np jeden składnik co mam w lodówce i np 3 inne, które musiałbym kupic... A to już odpada...
Go to the top of the page
+Quote Post
dymsza
post
Post #15





Grupa: Zarejestrowani
Postów: 62
Pomógł: 4
Dołączył: 24.08.2006

Ostrzeżenie: (0%)
-----


robisz pod zapytanie wtedy

  1. SELECT s.id form salatki AS WHERE s.id IN NOT IN (SELECT s.id form salatki AS LEFT JOIN xref AS k ON k.id_c = s.id WHERE k.id_c IS NOT IN (1,9,11,12) GROUP BY s.id)


  1. jak BY nie działało TO spróbuj jeszcze tak
  2.  
  3. SELECT s.id form salatki AS WHERE NOT s.id =
  4.  
  5. (SELECT s.id form salatki AS LEFT JOIN xref AS k ON k.id_c = s.id WHERE k.id_c IS NOT IN (1,9,11,12) GROUP BY s.id)


ale nie daje gwarancjii bo już nie pamietam
polecam zaponie się z tematyką pod zapytań http://republika.onet.pl/20405,16620,1,07,kursy.html
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 2.01.2026 - 09:49