kirkor0
16.12.2005, 14:06:55
mam dwie tebele polaczone ze soba polem pole_id. Chce pobrac dane z tabeli_1, ale tylko te wiersze o polu_id, korego wartosc nie znajduje sie w tabeli_2.
Czyli jezeli mamy pole_id o wartosci 2 w obu tabelach, to aby nie zwracal mi tego pola. Natomiast jezeli wartosc pola_id znajduje sie tylko w tabeli_1, aby pobral ta wartosc.
kszychu
16.12.2005, 14:52:41
SELECT tabela_1.*
FROM tabela_1, tabela_2 WHERE tabela_1.pole_id = tabela_2.pole_id
Tak ciężko zajrzeć do manuala i poczytać o złączeniach? Radzę to zrobić, bo to które pokazałem, jest akurat najprostrzym ze złączeń, a bez nich ani rusz.
adasoft
16.12.2005, 15:08:46
SELECT t1.nazwa, t1.DATA
FROM tabela_1 AS t1
JOIN tabela_2 AS t2 ON t1.pole_id=t2.pole_id
WHERE t1.pole_id<>t2.pole_id
Oczy 'nazwa' i 'data' to są pola przykładowe pobierane z tabeli_1
kirkor0
16.12.2005, 15:32:11
a po co uzywac tutaj aliasow? koniecznie?
nazwy tabel sa krotkie
nospor
16.12.2005, 17:10:02
aliasy nie są tu niezbedne, ale są krotrze nawet o tych twoich "krótkich" tabel.
Jabol
16.12.2005, 19:15:07
SELECT tabela_1.*
FROM tabela_1, tabela_2 EXCEPT SELECT tabela_1.*
FROM tabela_1, tabela_2 WHERE tabela_1.pole = tabela_2.pole;
FiDO
16.12.2005, 22:02:37
Ja bym zrobil tak:
SELECT t1.*
FROM tabela_1 t1
LEFT JOIN tabela_2 t2 USING(pole_id)
WHERE t2.pole_id IS NULL
Jabol
16.12.2005, 22:05:07
SELECT *
FROM table_1 WHERE pole_id NOT IN (SELECT pole_id
FROM table_2);
Hehe, ależ ten sql wypasiony

.
FiDO
16.12.2005, 22:40:03
Sposobow jest wiele, to fakt.. ale trzeba sie tez liczyc z optymalizacja zapytan.
Ostatnio robilem dosc skomplikowane zapytanie, najpierw za pomoca subquery, ale bylo nieludzko powolne (kilka zapytan prawie takich samych wykonywalo sie kilka sekund) mimo indexow na wszystkich polach, na ktorych byly jakies warunki.
Potem udalo mi sie po dlugich bojach zmienic to na joina (zostalo tylko jedno proste subquery) i czas wykonania spadl ok dziesieciokrotnie.
Jabol
16.12.2005, 23:18:26
@FiDo: Zaciekawiło mnie jeszcze jakby zrobić takie zapytanie, gdyby pola nie nazywały się tak samo (nie używając USING). Bo jeżeli użyjesz ON to przecież nie będzie złączeń z NULL. Czy może LEFT JOIN ... ON .. zwraca pola nawet te, które nie mają swoich odpowiedników?
kirkor0
16.12.2005, 23:36:50
Spoko, juz sobie poradzilem, juz popbralem, ale teraz trzeba mi je usunac.
Te wyniki ktore dostalem (zarowno z jednej jak i z drugiej tabeli) chce usunac.
Moze cos w stylu
DELETE
FROM tabela_1, tabela_2 WHERE pole_id IN(SELECT....)
to select to by bylo to co wyzej
a moze inaczej?
FiDO
17.12.2005, 00:12:32
@Jabol: jesli jest LEFT JOIN to juz niewazne jak zapisujesz zlaczenie.. i tak zwraca wszystkie rekordy z tabeli z lewej strony zlaczenia. USING w tym przypadku tylko skraca zapis.
@kirkor0: moze byc tak.
kirkor0
17.12.2005, 00:38:47
Ten kod, który podałem nie działa - spodziewałem się tego. To był tylko punkt mojego widzenia.
Co jest źle, a może inaczej?
FiDO
17.12.2005, 02:19:04
Podaj cale zapytanie jakie wykonales i najlepiej od razu komunikat bledu.
kirkor0
17.12.2005, 10:37:39
Moje zapytanie jest duzo bardziej rozbudowane. Musze uzyc 3 tabel.
DELETE
FROM table_1, table_2, table_3 WHERE id_poleIN (SELECT table_1.id_pole
FROM table_1 LEFT JOIN table_3 USING(id_pole) LEFT JOIN table_2 USING(id_pole) WHERE (NOW() > DATE_ADD(table_1.pole_1, INTERVAL 1 day) OR NOW() > DATE_ADD(table_2.pole_2, INTERVAL 1 day)) AND (table_1.id_pole=table_2.id_pole OR table_2.id_poleIS NULL) AND table_3.id_pole IS NULL)
I Nr błędu: 1064. Treść błędu: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE id_pole IN (SELECT table_1.id_pole FROM table_1 LEFT JOIN ta".
FiDO
17.12.2005, 11:34:51
Jesli chcesz z kazdej tabeli usunac wiersze, ktore nie maja swoich odpowiednikow w pozostalych tabelach to obawiam, ze za jednym zamachem sie tego nie da zrobic tak jak probujesz. Sprobuj to rozbic na osobne zapytania usuwajace z kazdej tabeli.
kirkor0
17.12.2005, 11:53:10
wszystkie pola sa polaczone polem pole_id.
ale mniejsza z tym, bo teraz bylby problem, bo jakbym usunal z jednej tabeli, to SELECT juz nie zwrocilby tych samych rekordow.
Wiec moze usunalbym z tabela_1, a potem usunal z innych tabeli te, które nie maja swojego odpowiednika w tabela_1. Tylko jak to zrobic?
SongoQ
17.12.2005, 14:03:38
@FiDO
Cytat
Potem udalo mi sie po dlugich bojach zmienic to na joina (zostalo tylko jedno proste subquery) i czas wykonania spadl ok dziesieciokrotnie.
Oczywiscie left join jest szybszy od podzapytan typu in ale nalezy uwazac na pewne rzeczy.
1 to wystrzegac sie zeby bylo jak najminejsza liczba zlaczen. Teoretycznie max powinno byc 5, kolejna rzeczy podzapytanie z IN sa strasznie wolne, gdzie IN zwraca wiele rekordow. Wiec trudno nieraz dopasowac zeby bylo ok. Ja mniej wiecej robie to w ten sposob ze laduje miliony rekordow w tabele i na zasadzie prob i bledow sprawdzam wszystkie warianty ale trzeba sie liczyc z czasem.
kirkor0
18.12.2005, 11:57:08
Nikt nie wie jak?
Mam dwie tabele połączone polem pole_id. Chodzi mi o usunięcie rekordów z jednej tabeli, tych które nie mają swojego odpowiednika w drugiej tabeli.
Inaczej mowiac jeżeli w tabeli_2 znajduje sie rekord o polu_id np. 4 i nie istnieje rekord o polu pole_id w tabeli_2, to niech zostanie usunięty.
Jabol
18.12.2005, 12:42:40
Ja bym to zrobił poprzez
DELETE
FROM tabela_1 USING tabela_2 WHERE tabela_1.pole_id = tabela_2.pole_id;
Ale USING jest rozszeżeniem SQL'a dodawanym w postgresie. Nie wiem, jak jest w innych bazach. Musisz poszukać analogicznego sposobu albo zrobić rzeczywiście z subquery.
kirkor0
18.12.2005, 15:38:04
Nie zrozumiales mnie.
- Jezeli w obu tabelach sa rekordy z polem_id o takiej samej wartosci, to nie chce nic usuwac.
- Jezeli w tabeli_1 jest rekord o danym id, a w tabeli_2 nie ma tego id, to nie chce nic usuwac
- Jezeli w tabeli_1 nie ma pola_id, a dane id znajduje sie w tabeli_2, to chce ten rekord usunac
Inaczej mowiac usun rekordy z tabeli_2, ktore nie maja swojego odpowiednika w tabeli_1.
===
Jeszcze inaczej. Mam tabele userzy i tabele posty. Chcialem usunac uzytkownika z tabeli userzy i tabeli posty. Niestety nie wiem jak to zrobic w jednym zapytaniu. Wiec najpierw usuwam dane o uzytkowniku z tabeli userzy, a potem z tabeli posty.
Czyli chce usunac te posty, kore sa bezpanskie - nie maja swojego uzytkownika.
OT. Oczywiscie, ze wolalbym za jednym razem usunac wszystkie dane o uzytkowniku za jednym zamachem - tak byloby najlepiej, ale nie wiedzieliscie jak.
Synaps
20.12.2005, 11:29:06
Wyglada mi na to ,że kolega zapomniał o więzach integralności i baza mu się rozspójniła

Nauczka na przyszłość...dobry projekt.
DELETE
FROM tabela_1 WHERE NOT EXISTS ( SELECT 'X'
FROM tabela_2 WHERE tabela_2.id = tabela_1.id )
To powinno rozwiązać Twój problem.
kirkor0
21.12.2005, 00:32:06
Dzieki o to mi chodzilo.
Zadna baza mi sie nie rozspujnila.
Chodzi mi o usuniecie nieaktywnych uzytkownikow - ktorzy np nie logowali sie przez ostatni miesiac. Dane o uzytkownikach sa przechowywane w kilku tabelach, a te tabele sa polaczone jednym polem id.
Nadal nie wiem jak usunac ich za jednym zapytaniem, wiec wpadlem na pomysl aby usunac dane z tabeli users, a potem usunac dane z innych tabel, ktore nie maja swoich odpowiednik w tabeli users.
Ale jak ktoś zna sposób na zrobienie tego w jednym zapytaniu, to niech się pochwali!
SongoQ
21.12.2005, 00:46:57
Mozesz np po przez relacje caskadowa.
kirkor0
23.12.2005, 23:49:55
... może jaśniej?
nospor
23.12.2005, 23:59:04
moze poczytaj se cos o relacjach i o kaskadowym usuwaniu.
Tabele maja byc typu innodb, zakladasz klucz obcy w jednej tabeli i okreslasz jak ma sie zachowywyac w przypadku kasowania glownego rekordu.
tutaj tez cos bylo
http://forum.php.pl/index.php?showtopic=7816
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.