Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [MySQL]Wyciągnięcie danych z kilku tabel
@rtur
post
Post #1





Grupa: Zarejestrowani
Postów: 254
Pomógł: 3
Dołączył: 23.02.2006

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


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ę.
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 10)
c4ash
post
Post #2





Grupa: Zarejestrowani
Postów: 73
Pomógł: 9
Dołączył: 14.01.2010

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


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
Go to the top of the page
+Quote Post
@rtur
post
Post #3





Grupa: Zarejestrowani
Postów: 254
Pomógł: 3
Dołączył: 23.02.2006

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


  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'.
Go to the top of the page
+Quote Post
nospor
post
Post #4





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




No to czemu przy pomocy JOIN nie dodasz kolejnej interesujacej cie tabeli?
Go to the top of the page
+Quote Post
@rtur
post
Post #5





Grupa: Zarejestrowani
Postów: 254
Pomógł: 3
Dołączył: 23.02.2006

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


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
Go to the top of the page
+Quote Post
nospor
post
Post #6





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




....
Pokaz kod po zastosowaniu JOIN jak ci pisalem. SKadm mam wiedziec co zepsules.... wrozyc mam?
Go to the top of the page
+Quote Post
@rtur
post
Post #7





Grupa: Zarejestrowani
Postów: 254
Pomógł: 3
Dołączył: 23.02.2006

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


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. );
Go to the top of the page
+Quote Post
nospor
post
Post #8





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




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?
Go to the top of the page
+Quote Post
@rtur
post
Post #9





Grupa: Zarejestrowani
Postów: 254
Pomógł: 3
Dołączył: 23.02.2006

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


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. );


Ten post edytował @rtur 25.11.2013, 21:59:58
Go to the top of the page
+Quote Post
nospor
post
Post #10





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




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
Go to the top of the page
+Quote Post
@rtur
post
Post #11





Grupa: Zarejestrowani
Postów: 254
Pomógł: 3
Dołączył: 23.02.2006

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


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 (IMG:style_emoticons/default/smile.gif)
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: 23.08.2025 - 03:52