Mysql, kłopot z wyrażeniem do wyszukiwania

Czyli: tabela1 > tabela2 > tabela3

Jak teraz wyszukać po polu fraza by w wynik wyświetlić w takiej postaci:

nazwa (tabela1), nazwa (tabela2), nazwa (tabela3) : fraza (tabela3)

normalnie pisząć: SELECT * FROM tabela3 WHERE fraza=test

otrzymam tylko tekst z pól nazwa i fraza z tabela3 i identyfikatory rekordów z tabela 1 i tabela2, nie ich nazwy

I jak przy wyszukiwaniu nie rozróżniać wielkości liter, żeby pisząc LIKE fraza=%test% wyszukiwało mi: test jak i TeSt, TEST itd.?

Mam nadzieje że dobrze wytłumaczyłem :oops:

Może pójdzie:

SELECT tabela3.*,tabela2.nazwa as nazwa2 FROM tabela3,tabela2 WHERE tabela3.fraza="test" and tabela3.tabela2=tabela2.id

Zobacz czy idzie Ci to z tabelą 3 i 2. Jak idzie to “podłączymy” jeszcze tabelę 1. Zauważ, że pole nazwa z tabeli2 zostało tymczasowo zmienione

tabela2.nazwa as nazwa2

żeby nie kolidowało z polem o tej samej nazwie z tabeli 3 @EDIT: a co do wielkości liter to można np. tak:

where upper(fraza) like upper('%test%')

niech to jasna ciasna.

Z Poszerzeniem prostego przykładu dałem sobie rade ale w praktyce się kiełbasi

Teraz analogicznie chcę połączyć te 4 tabele polami id, kraj, region, miasto, punkt i pobrać pola nazwa , z tym że:

-tabela kraj jest nadrzędna.

-pole kraj tabeli region = polu id tabeli kraj

-pole kraj tabeli miasto = polu kraj tabeli region

-pole region tabeli miasto = polu id tabeli region

-pole kraj tabeli punkt = polu kraj tabeli miasto

-pole region tabeli punkt = polu region tabeli miasto

-pole miasto tabeli punkt = polu id tabeli miasto

o ile mi się nic nie pokićkało

Jak to połączyć?

Złączono Posta : 14.08.2007 (Wto) 2:12

udało mi się połączyć

Ale są dwa problemy.

-jak dodam jeszcze wyszukiwanie

to się wykrzacza

-jeżeli dany rekord ma braki to się krzaczy

konkretnie region , nie jest on obowiązkowy i gdy w danym kraju nie mam podziału na regiony, w tabelach miasto i punkt pole region=0 - a t nie ma odpowiednika w tabelach kraj i region

pewnie IF należy użyć albo coś innego ale jak?

Złączono Posta : 14.08.2007 (Wto) 2:26

kombinowałem tak

Ale nie pokazuje dalej wszystkich punktów. Nie pokazuje tych gdzie w tabeli punkt i miasto pole region=0.

Dla wyjaśnienia, numeracja pól id wszędzie zaczyna się od 1

Nie do końca rozumiem, ale może w ten sposób:

Pole region masz INT NOT NULL, zmień je tak, aby można było umieścić wartość NULL. Jeśli region nie jest wymagany, “insertuj” mu właśnie NULL. Potem przy pobieraniu sprawdzaj czy pole region nie jest puste. I w zależności zrób odpowiednie warunki. Jeśli nie jest puste postępuj normalnie, a jeśli nie, przerób warunek aby nie zwracał uwagi na region.

pola region zmieniłem na NULL i tak też dodaję do bazy.

Problem jednak pozostaje

Ale może bardziej obrazowo,

zgaduje że problem pojawia się na lini tego przypisania:

pole region tabeli miasto = polu id tabeli region

czyli w zapytaniu: miasto.region=region.id (a to ciągnie za sobą kolejne zwalone przypisanie punkt.region=miasto.region )- bo punkt.region i miasto.region mogą mieć wartość NULL , a to nie ma wówczas odzwierciedlenia w region.id będącym NOT NULL i dodatkowo prumary key

Dlatego post wcześniej kombinowałem z IF w zapytaniu ale to mi nie chce działać, bo zwraca i tak tylko rekordy gdzie region <> NULL

Jak poprawić to zapytanie by zwracało również rekordy gdzie w tabelach miasto i punkt , pole region ma wartość NULL ??

Hmmm… a może nie tu drogi szukamy. Spróbuj w ten sposób:

where ... AND (miasto.region=NULL OR (miasto.region=region.id))

wyrażenie połączone operatorem logicznym LUB (OR) będzie miało wartość TRUE jeśli przynajmniej jedno z podwyrażeń będzie TRUE. Dlatego powinno zwrócić wszystko…

Więc jeśli się nie pomyliłem powinno wyglądać tak:

"SELECT punkt.id AS pid, punkt.nazwa AS nazwa_p, miasto.nazwa AS nazwa_m, region.nazwa AS nazwa_r, kraj.nazwa AS nazwa_k FROM punkt, miasto, region, kraj WHERE (region.kraj=kraj.id AND miasto.kraj=region.kraj AND (miasto.region=NULL OR (miasto.region=region.id)) AND punkt.kraj=miasto.kraj AND (punkt.region=NULL OR (punkt.region=miasto.region)) AND punkt.miasto=miasto.id)"

Niestety nadal nie działa jak powinno :frowning:

-dalej pokazuje tylko te rekordy gdzie

Czy zrobiłem gdzieś jakiś błąd?

Już mnie coś bierze przy tym.

Przed chwilą sprawdziłem czy z tym NULL się nie przejechałem… i kurczę… hehe, chyba tak. Chodzi o to, że (przynajmniej mi) po warunku z NULL nic nie zwróciło. Więc może zamiast:

miasto.region=NULL

wstaw

miasto.region=''

Do testow wgrałem baze testową

i w pliku testowym dałęm

i w wynikach pokazuje mi tylko

czyli nie pokazuje mi:

4 - Niemcy , , Berlin , test4 -gdzie nie ustawiono regionu dla miasta Berlin i punktu test4

Co więcej, chcial bym by pokazywało jeszcze:

5 - Francja , , Paryż , , - gdzie brak regionu dla miasta Paryż i brak ustawionych punktów w tym mieście.

Czyli chcę uzyskać listę postaci:

kraj, region, miasto, punkt

i

kraj, miasto, punkt -gdy brak regionu

i

kraj, region, miasto -gdy brak punktów dla tego miasta

i

kraj, miasto -gdy brak regionu i punktów dla tego miasta

Da radę?

Chyba w końcu zrozumiałem o co Ci chodzi :slight_smile:

Więc tak, w ten sposób, jaki chcesz nie da się pobrać raczej. Po prostu jeśli dane pole jest NULL, to nie ma dla niego relacji. Jeśli jego wartość nie istnieje to nie można go porównać z innym polem.

Są 2 wyjścia, jedno bardziej wydajne i lepsze, drugie zdecydowanie gorsze.

  1. w tabeli region ustawiasz jeden rekord, gdzie w “kraj” będzie miał jakąś niepowtarzalną wartość (np. 0 - zero) a w “nazwa” nie będzie miał nic. Następnie w tabeli miasto w polu “region” będzie miał właśnie to zero. Wtedy relacja zadziała w 100%.

  2. Pobierasz wszystko i w PHP filtrujesz, ale w ten sposób jeśli będziesz miał dużo danych w bazie, możesz zabić serwer.

  1. odpada a 1. - już cos podobnie kombinowałem tu jednak pojawia się kłopot bo jak w regionie zrobię rekord bez nazwy z polem kraj=0, to relacja w dół może i będzie ale nie powiąże rekord.kraj=kraj.id

Już myślę żeby rozdzielić wyszukiwanie selectem oddzielnie na kraj, region, miasto, punkt - to częściowo rozwiąze problem

W takim razie nie pozostaje już Ci nic innego jak wstawienie obowiązkowego regionu, albo jak sam powiedziałeś rozbicie na kilka zapytań.

Kombinuje może strasznie ale wywaliłem region - całą tebele region i pola region z pozostałych 3tabel.

Czy dla samych tabel kraj, miasto, punkt da rady zrobić zapytanie by zwracało wszystkie rekordy gdzie relacja kraj>miasto>punkt i kraj>miasto (brak zdefiniowanych punktów)??

czyli wszystkie punkty+miasta bez zdefiniowanych punktów

Jeżeli jakieś rekordy mają swoje punkty, a inne nie, to tak samo jak w przypadku regionu, relacja nie zadziała. Więc najlepszym rozwiązaniem byłoby po prostu danie obowiązkowych punktów.

A właściwie to co chcesz przechowywać w tabeli punkt? Bo jak tak patrzę na strukturę Twojej bazy, to tak się zastanawiam czy nie można by jej uprościć :slight_smile:

Tego się spodziewałem :frowning:

Właśnie nie tylko punkty, a szkoda bo by jedna tabelka wtedy starczyłą.

wporzo, podzieliłem sobie i wyszukuję rekordów w wybranej tabeli po słowach kluczowych w 2 polach.

Mam taki kod

I działa, ale za dobrze. Bo potworzyłem sobie dodatkowo w każdej tabeli rekord o nazwie test i ze słowem test w polu url i teraz w wyszukiwaniu po kraju jest spox - tylko jedna tabela.

Ale kłopot pojawia się w pozostałych, bo tam dołączone są tabele miasto i kraj. No i w nich jak by wyszukiwało nie tylko po polach punkt.url, punkt.nazwa i miasto.url, miasto.nazwa, gdzie dzięki relacjom miał bym niezbędne dane z nadrzędnych tabel ale jak by szukało po polach url i nazwa we wszystkich dołączonych tabelach bo wyniki mam 2 dla miasta (miasto+kraj) i 3 dla punktu (punkt+miasto+kraj)

Jak to poprawić?

Nagmatwałeś… ojojoj… :slight_smile: ciężko zrozumieć…

hmmm… czyli zwraca 2 lub 3 te same rekordy?

Jeśli dobrze rozumiem to użyj DISTINCT .

http://dev.mysql.com/doc/refman/4.1/en/ … ation.html

http://sql.pressmedia.com.pl/distinct.htm

:mrgreen:

Włąśnie chyba nie te same tylko z wszystkich tabel a nie z tej co sobie wybrałem.

Wywaliłem z zapytania dowiązane tabele i jest ok, a dane z tamtych dociągne sobie może inaczej.