Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> SELECT
Athlan
post
Post #1





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Ajjj... dawno nie pisałem (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Więc witam (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Mój problem polega na tym, że potrzebuje wybrać dane z drugiej tabeli, jednakże LEFT JOIN tu zawodzi.

Posiadam tabele:
  1. --
  2. -- Struktura tabeli dla `notes`
  3. --
  4.  
  5. CREATE TABLE `notes` (
  6. `note_id` int(11) NOT NULL AUTO_INCREMENT,
  7. `note_blog` int(11) NOT NULL,
  8. `note_author` int(11) NOT NULL,
  9. `note_time` int(11) NOT NULL,
  10. `note_update` int(11) NOT NULL,
  11. `note_title` varchar(255) NOT NULL,
  12. `note_rewrite` varchar(255) NOT NULL,
  13. `note_text` longtext NOT NULL,
  14. `note_active` enum('y','n') NOT NULL DEFAULT 'n',
  15. `note_comments` enum('y','n') NOT NULL DEFAULT 'y',
  16. PRIMARY KEY (`note_id`),
  17. KEY `note_rewrite` (`note_rewrite`),
  18. KEY `note_blog` (`note_blog`),
  19. KEY `note_time` (`note_time`),
  20. KEY `note_author` (`note_author`),
  21. KEY `note_active` (`note_active`),
  22. KEY `note_update` (`note_update`)
  23. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
  24.  
  25. -- --------------------------------------------------------
  26.  
  27. --
  28. -- Struktura tabeli dla `tags`
  29. --
  30.  
  31. CREATE TABLE `tags` (
  32. `tag_name` varchar(255) NOT NULL,
  33. `tag_note` int(11) NOT NULL,
  34. `tag_blog` int(11) NOT NULL,
  35. PRIMARY KEY (`tag_name`,`tag_note`),
  36. KEY `tag_blog` (`tag_blog`)
  37. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Przy zapytaniu:
  1. SELECT * FROM notes

chciałbym pobrać również wszystkie rekordy z tabeli tags gdzie tag_note = note_id przypisane do wybieranego rekordu.

LEFT JOIN pobierze tylko jeden tag (rekord z tabeli tags), a chciałbym otrzymać wszystkie w jednym zapytaniu. Jakieś sugestie? Dzięki za odpowiedź (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Pozdrawiam, Athlan
Go to the top of the page
+Quote Post
Norbas
post
Post #2





Grupa: Zarejestrowani
Postów: 100
Pomógł: 1
Dołączył: 6.02.2006

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


Szczerze mówiąc nie wiem z czym masz problem. Zastoswanie LEFT JOIN powinno zwrócić wszystkie powiązane rekordy z tabeli 'tags' a nie tylko jeden jak piszesz. Może grupujesz wyniki zapytania? Zapytanie może wyglądać następująco:
  1. SELECT notes.*,tags.*
  2. FROM notes LEFT JOIN tags ON tags.tag_note=notes.note_id
Go to the top of the page
+Quote Post
Athlan
post
Post #3





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


@Norbas, zanim coś napiszesz sprawdź czy to działa (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

LEFT JOIN przypina z lewej strony (czyli dane mogą nie istnieć) TYLKO I WYŁĄCZNIE kolejne pola, nie rekordy.
RIGHT JOIN przypina pola z prawej strony, czyli nasz rekord który przpinamy z drugiej tabeli MUSI istnieć.

Pozdro (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
Norbas
post
Post #4





Grupa: Zarejestrowani
Postów: 100
Pomógł: 1
Dołączył: 6.02.2006

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


Dobra sprawdziłem, chociaż nigdy nie sprawdzam tak prostych zapytań (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Załóżmy, że mamy taką strukturę tabel jak podałeś. Dopisujemy dane:
  1. INSERT INTO `notes` (`note_id`) VALUES (1),(2);
  2. INSERT INTO `tags` (`tag_name`, `tag_note`) VALUES ('t1', 1), ('t2', 1), ('t2', 2);

Czyli tagi 't1' i 't2' są powiązane z pierwszą notatką, zaś 't2' z drugą.
Po wykonaniu zapytania, które podałem (z ewentualnym sortowaniem) otrzymamy (pomijam nieistotne pola z obu tabel):
Kod
note_id | tag_name
   1    |   t1
   1    |   t2
   2    |   t2

czyli moim zdaniem tak jak chciałeś:
Cytat
chciałbym pobrać również wszystkie rekordy z tabeli tags gdzie tag_note = note_id przypisane do wybieranego rekordu.

Chyba, że inaczej rozumiemy słowo rekord?
Go to the top of the page
+Quote Post
AcidBurnt
post
Post #5





Grupa: Zarejestrowani
Postów: 215
Pomógł: 1
Dołączył: 13.04.2003
Skąd: z ławki przed blokiem

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


orpocz left i right sa jeszcze alter, inner join, sprawdz, ja nigdy nie pameitam ktory co robi ;]
Go to the top of the page
+Quote Post
Athlan
post
Post #6





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Norbas, misiu...

Cytat
chciałbym pobrać również wszystkie rekordy z tabeli tags gdzie tag_note = note_id przypisane do wybieranego rekordu.
Go to the top of the page
+Quote Post
Norbas
post
Post #7





Grupa: Zarejestrowani
Postów: 100
Pomógł: 1
Dołączył: 6.02.2006

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


Cytat
Norbas, misiu...
Ale czułości, żebyś chociaż był kobietą (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

Widzę, że dalej się nie rozumiemy. Przecież otrzymasz wszystkie powiązane rekordy z tagami.

Domyślam się co chcesz uzyskać (ale tego nie napisałeś): chcesz wyświetlić listę notatek z tagami przyporządkowanymi do danej notatki. Jeżeli tak, to można zastosować zapytanie, które podałem, ale jest w tym wypadku problem ze stronicowaniem, gdyż nie wiadomo ile tagów jest przyporządkowane do danej notatki. Moim zdaniem w takiej sytuacji jedno zapytanie nie wystarczy. W takim wypadku proponuję inne rozwiązanie.
Wykonujesz zapytanie o notatki:
  1. SELECT * FROM notes ORDER BY ...
  2. LIMIT ...

W pętli przetwarzasz wyniki zapytania wstawiając je do tablicy wyników i rezerwujesz jeden element takiej tablicy na tagi przyporządkowane do danej notatki:
Kod
$returns[$rows['note_id']] = array(
  'note_blog' => $row['note_blog'],
//  itd. (pola, które są potrzebne)
  'tags' => array()
);


Następnie mając identyfikatory notatek wykonujesz drugie zapytanie tylko o tagi dla odczytanych identyfikatorów:
Kod
'SELECT * FROM tags WHERE tag_note IN (' . impode(',', array_keys($returns)) . ')'


W kolejnej pętli dodajesz odczytane wyniki tego zapytania do odpowiedniego elementu tablicy wyników:
Kod
$returns[$row['tag_note']['tags'][] = array(
  'tag_name' => $row['tag_name'],
  'tag_blog' => $row['tag_blog']);


Jeżeli źle się domyślam, to pokaż na danych, które podałem jakie wyniki chcesz uzyskać.

Ten post edytował Norbas 27.06.2007, 22:58:08
Go to the top of the page
+Quote Post
Athlan
post
Post #8





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Norbas, właśnie dokładnie tak mam rozwiązane kategorie linków... no inaczej chyba się nie dało.

Chciałem się dowiedzieć, czy sam wpadłem na ten pomysł i czy się nie da tego jakoś prościej. Najwidoczniej trzeba sobie to filtrować w PHP samemu, tak jak zrobiłem to z linkami i jak podałeś wyżej.

No nic... trudno. Btw, ze stronnicowaniem nie będzie problemu (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
envp
post
Post #9





Grupa: Zarejestrowani
Postów: 359
Pomógł: 1
Dołączył: 16.04.2006
Skąd: Łódź

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


A może najprościej zrobil LEFT JOIN notes a nie tags ? (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Pozdrawiam, Kamil
Go to the top of the page
+Quote Post
SongoQ
post
Post #10





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

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


Panowie to jest jakas amatorka. LEFT JOIN przeciez to jak witaj swiecie.
Go to the top of the page
+Quote Post
Athlan
post
Post #11





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Cytat
A może najprościej zrobil LEFT JOIN notes a nie tags ? smilingsmiley.gif Pozdrawiam, Kamil

i tu może być problem z stronnicowaniem notek (dokładniej limitami), taki pomysł też miałem, bo duble notes można łatwo usunąć. Może nie tyle problem, bo to też się da. Ale jak przypisujemy po 7 - 12 tagów na notkę, to mnie się wydaje że to nie będzie wydajne.

Cytat
Panowie to jest jakas amatorka. LEFT JOIN przeciez to jak witaj swiecie.

Coś sugerujesz? (IMG:http://forum.php.pl/style_emoticons/default/snitch.gif) Jakaś recepta na problem?

Póki co mamy 3 pomysły:
- przelecieć foreachem i dokonać kolejne zapytania osobno na każdą notkę, czyli na każdą notkę osobne zapytanie o tagi (najgorsze, ale jak będzie cache to nie wiem...)
- zaznaczyć tagi i joinować notki (tak jak to przedstawił Kamil)
- wykonać 2 zapytania: o notki, a następnie o tagi z wyróżnieniem ID notek, które zostały wybrane i połączyć to w php (póki co najlepszy pomysł)
Go to the top of the page
+Quote Post
SongoQ
post
Post #12





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

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


Cytat
Coś sugerujesz? (IMG:http://forum.php.pl/style_emoticons/default/snitch.gif) Jakaś recepta na problem?

Nie chodzilo mi o problem tylko o znajomosc LEFT JOIN
Go to the top of the page
+Quote Post
Athlan
post
Post #13





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Wybrałem trzeci sposób z przedstawionych 2 posty wyżej.

Oto rozwiązanie:

  1. <?php
  2. // pobieramy notki (tutaj bez stronnicowania, lecz dojdzie obiekt pagera)
  3. $this->oView->aNotes = $aNotes = $this->setModel('note')->get(null, $this->_aBlogData['blog_id']);
  4. // zbierami ID pobranych notek
  5. $aUsedNotes = array();
  6. foreach($aNotes as $iKey => $aRow)
  7. $aUsedNotes[] = $aRow['note_id'];
  8. // pobieramy tagi przypisane do zebranych postów
  9. $aTags = $this->setModel('tag')->getUsed($aUsedNotes);
  10. // przypisujemy tagi: ID_NOTKI => array(TAG, TAG, TAG [... itd ...]);
  11. $aUsedTags = array();
  12. foreach($aTags as $iKey => $aRow)
  13. {
  14. if(!is_array($aUsedTags[$aRow['tag_note']]))
  15.  $aUsedTags[$aRow['tag_note']] = array();
  16.  
  17. $aUsedTags[$aRow['tag_note']][] = $aRow['tag_name'];
  18. }
  19. // koniec :)
  20. $this->oView->aTags = $aUsedTags;
  21. ?>


Chyba najbardziej optymalne rozwiązanie. Dziękuję za dyskusję (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Athlan (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
envp
post
Post #14





Grupa: Zarejestrowani
Postów: 359
Pomógł: 1
Dołączył: 16.04.2006
Skąd: Łódź

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


@Athlan: jedna z zasad optymalizacji skryptów - jeśli da się zrobić coś na poziomie bazy - to to zrób. Kiedys robiłem testy na zapytania do mysl'a i uwierz lepiej zrobić jedno duże zapytanie niż kilka mniejszych...
Go to the top of the page
+Quote Post
Athlan
post
Post #15





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Cytat
@Athlan: jedna z zasad optymalizacji skryptów - jeśli da się zrobić coś na poziomie bazy - to to zrób. Kiedys robiłem testy na zapytania do mysl'a i uwierz lepiej zrobić jedno duże zapytanie niż kilka mniejszych...


Sugerujesz, żeby joinować notki do tagów i wykonać wszystkie operacje?
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: 16.09.2025 - 01:09