Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL]Wyciągnięcie danych z kilku tabel
Forum PHP.pl > Forum > Przedszkole
@rtur
Kompletnie nie potrafię pojąć wszelkich złączeń w mysql, mam takie tabele:

wykonawcy:
  1. wykonawca_id|wykonawca_name
  2. 8|Nazwa wykonawcy

utwory:
  1. utwor_id|wykonawca_id|utwor_tytul
  2. 46|8|Tytuł utworu

ile_grane:
  1. grane_id|utwor_id|ilosc
  2. 1|46|74


Mogę poprosić o pomoc w złożeniu zapytania które wyciągnie mi takie dane w jednym zapytaniu mysql?

  1. wykonawcy.wykonawca_id|wykonawcy.wykonawca_name|utwory.utwor_id|utwory.utwor_tytul|ile_grane.ilosc
  2. 8|Nazwa wykonawcy|46|Tytuł utworu|74


Może jakoś na gotowym przykładzie, na własnych danych łatwiej to rozgryzę.
c4ash
Laczysz zapytanie w jedno z kilku tabel za pomoca join

Przykład: http://webmaster.helion.pl/index.php/kursm...wynikow-zapytan

Albo najlepiej wybierz sobie cos google
@rtur
  1. SELECT u.utwor_id,w.wykonawca_id,u.utwor_tytul,w.wykonawca_name FROM utwory AS u INNER JOIN wykonawcy AS w USING (wykonawca_id)

takim zapytaniem z dwóch tabel mi się udało wyciągnąć dane i dopasować wykonawce do utworu ale nie mogę wpaść na to jak skonstruować to zapytanie żeby teraz zobaczyć dodatkowo dane na temat tych utworów z tabeli 'ile_grane'.
nospor
No to czemu przy pomocy JOIN nie dodasz kolejnej interesujacej cie tabeli?
@rtur
dodałem JOIN ile_grane as ig i dostaje #1054 unknown column 'wykonawca_id' in 'from clause' a jak dam w usign utwor_id to dostaje wynik ale jak jest 2 wykonawców to wyświetla 2 wiersze i wygląda to mniej więcej tak:
  1. utwor_id|wykonawca_id|utwor_tytul|wykonawca_name|ilosc
  2. 1|1|tytuł utworu 1|wykonawca 1|12
  3. 1|2|tytuł utworu 1|wykonawca 2|12


a do wykonawcy 2 nie ma przypisanego żadnego utworu
nospor
....
Pokaz kod po zastosowaniu JOIN jak ci pisalem. SKadm mam wiedziec co zepsules.... wrozyc mam?
@rtur
proszę, cała zawartość przykładowej bazy łącznie z problematycznym zapytaniem:

  1. CREATE TABLE IF NOT EXISTS `ile_grane` (
  2. `grane_id` int(11) NOT NULL AUTO_INCREMENT,
  3. `utwor_id` int(11) NOT NULL,
  4. `ilosc` int(11) NOT NULL,
  5. PRIMARY KEY (`grane_id`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=2 ;
  7.  
  8. INSERT INTO `ile_grane` (`grane_id`, `utwor_id`, `ilosc`) VALUES
  9. (1, 1, 12);
  10.  
  11. CREATE TABLE IF NOT EXISTS `utwory` (
  12. `utwor_id` int(11) NOT NULL AUTO_INCREMENT,
  13. `wykonawca_id` int(11) NOT NULL,
  14. `tytul` varchar(255) COLLATE utf8_polish_ci NOT NULL,
  15. PRIMARY KEY (`utwor_id`)
  16. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=2 ;
  17.  
  18. INSERT INTO `utwory` (`utwor_id`, `wykonawca_id`, `tytul`) VALUES
  19. (1, 1, 'Tytuł utworu 1');
  20.  
  21. CREATE TABLE IF NOT EXISTS `wykonawcy` (
  22. `wykonawca_id` int(11) NOT NULL AUTO_INCREMENT,
  23. `wykonawca` varchar(255) COLLATE utf8_polish_ci NOT NULL,
  24. PRIMARY KEY (`wykonawca_id`)
  25. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=3 ;
  26.  
  27. INSERT INTO `wykonawcy` (`wykonawca_id`, `wykonawca`) VALUES
  28. (1, 'Wykonawca 1'),
  29. (2, 'Wykonawca 2');
  30.  
  31. SELECT u.utwor_id,w.wykonawca_id,u.tytul,w.wykonawca,ig.ilosc FROM utwory AS u INNER JOIN wykonawcy AS w INNER JOIN ile_grane AS ig USING (utwor_id);


wynik zapytania wyexportowany do tablicy PHP:
  1. $utwory = array(
  2. array('utwor_id'=>1,'wykonawca_id'=>1,'tytul'=>'Tytuł utworu 1','wykonawca'=>'Wykonawca 1','ilosc'=>12),
  3. array('utwor_id'=>1,'wykonawca_id'=>2,'tytul'=>'Tytuł utworu 1','wykonawca'=>'Wykonawca 2','ilosc'=>12)
  4. );
nospor
robisz JOIN na wykonawcy, ale nie mowisz po jakim polu i z czym go laczysz.... nic wiec dziwnego ze taki wypadku baza zwraca ci wszelkie mozliwe kombinacje. Zawsze musisz laczyc jakims polem tabele.

I poczytaj o ON, ktore jest bardziej czytelne od USING

ps: a jaki w ogole sens ma tabela ile_grane? Czemu poprostu nie zrobisz w tabeli utwor kolejnego pola?
@rtur
Tam faktycznie można było sobie odpuścić tabele ile_grane i wrzucić te dane w tabele utwor i tak tez zrobiłem, ale trochę zmieniłem koncepcje i teraz w oddzielnej tabeli 'kiedygrane' trzymam dane na temat statystyk kiedy był grany dany utwór

  1. CREATE TABLE IF NOT EXISTS `kiedygrane` (
  2. `kg_id` int(11) NOT NULL AUTO_INCREMENT,
  3. `utwor_id` int(11) NOT NULL,
  4. `datetime` datetime NOT NULL,
  5. `type` int(11) NOT NULL,
  6. PRIMARY KEY (`kg_id`)
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=7 ;
  8.  
  9. INSERT INTO `kiedygrane` (`kg_id`, `utwor_id`, `datetime`, `type`) VALUES
  10. (1, 7, '2013-11-03 06:00:00', 0),
  11. (2, 6, '2013-11-12 10:24:15', 0),
  12. (3, 3, '2013-11-25 00:00:00', 1),
  13. (4, 6, '2013-11-11 15:22:47', 0),
  14. (5, 4, '2013-11-11 17:52:47', 1),
  15. (6, 1, '2013-11-16 17:52:47', 0);
  16.  
  17. CREATE TABLE IF NOT EXISTS `utwory` (
  18. `utwor_id` int(11) NOT NULL AUTO_INCREMENT,
  19. `wykonawca_id` int(11) NOT NULL,
  20. `tytul` varchar(255) COLLATE utf8_polish_ci NOT NULL,
  21. `ile_grane` int(11) NOT NULL DEFAULT '0',
  22. `pierwszy_raz` datetime DEFAULT NULL,
  23. `uwagi` text COLLATE utf8_polish_ci,
  24. PRIMARY KEY (`utwor_id`)
  25. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=8 ;
  26.  
  27. INSERT INTO `utwory` (`utwor_id`, `wykonawca_id`, `tytul`, `ile_grane`, `pierwszy_raz`, `uwagi`) VALUES
  28. (1, 1, 'Tytuł utworu 1', 0, NULL, NULL),
  29. (2, 7, 'Tytuł utworu 2', 0, NULL, NULL),
  30. (3, 5, 'Tytuł utworu 3', 0, NULL, NULL),
  31. (4, 3, 'Tytuł utworu 4', 0, NULL, NULL),
  32. (5, 5, 'Tytuł utworu 5', 0, NULL, NULL),
  33. (6, 6, 'Tytuł utworu 6', 0, NULL, NULL),
  34. (7, 2, 'Tytuł utworu 7', 0, NULL, NULL);
  35.  
  36. CREATE TABLE IF NOT EXISTS `wykonawcy` (
  37. `wykonawca_id` int(11) NOT NULL AUTO_INCREMENT,
  38. `wykonawca` varchar(255) COLLATE utf8_polish_ci NOT NULL,
  39. PRIMARY KEY (`wykonawca_id`),
  40. UNIQUE KEY `wykonawca` (`wykonawca`)
  41. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=9 ;
  42.  
  43. INSERT INTO `wykonawcy` (`wykonawca_id`, `wykonawca`) VALUES
  44. (1, 'Wykonawca 1'),
  45. (2, 'Wykonawca 2'),
  46. (3, 'Wykonawca 3'),
  47. (4, 'Wykonawca 4'),
  48. (5, 'Wykonawca 5'),
  49. (6, 'Wykonawca 6'),
  50. (7, 'Wykonawca 7'),
  51. (8, 'Wykonawca 8');

poniższe zapytanie chyba działa ok, ale pytanie czy jest optymalne, bo w oryginale ma działać na dużo większej bazie, każda z tabel ma więcej kolumn (utwory: ~25000 rekordów; wykonawcy:~7000 rekordów; kiedygrane:~120000 rekordów)
  1. SELECT u.tytul,w.wykonawca,kg.datetime FROM utwory AS u INNER JOIN wykonawcy AS w ON u.wykonawca_id = w.wykonawca_id INNER JOIN kiedygrane AS kg ON u.utwor_id = kg.utwor_id WHERE type = 1 ORDER BY datetime ASC

Wynik zapytania wyeksportowany do tablicy php:
  1. $utwory = array(
  2. array('tytul'=>'Tytuł utworu 4','wykonawca'=>'Wykonawca 3','datetime'=>'2013-11-11 17:52:47'),
  3. array('tytul'=>'Tytuł utworu 3','wykonawca'=>'Wykonawca 5','datetime'=>'2013-11-25 00:00:00')
  4. );
nospor
Skoro type to 1 lub 0 to powinnno to byc tinyint a nie int.

Skoro chcesz optymalnosci to czas najwyzszy zainsteresowac sie czyms takim jak INDEKSY
@rtur
nieźle, przy ~79000 rekordów w tabeli 'kiedygrane' index na 2 pola i z wyniku:
  1. Wykonanie zapytania trwało 0.0300 sekund(y))
daje wynik w granicy
  1. Wykonanie zapytania trwało 0.0011 sekund(y))
dzięki smile.gif
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.
Invision Power Board © 2001-2025 Invision Power Services, Inc.