konto usunięte

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

Witam,

Mam taki problem...

Są dwie tabele:

"Klienci"
- id
- nazwisko

oraz "Kredyty"
- id_klienta
- id_kredytu
- kwota_kredytu

Próbuję skonstruować zapytanie SELECT aby pobierało dane: id i nazwisko z tabeli KLIENCI oraz id_kredytu oraz kwota_kredytu z tabeli KREDYTY i te dany wyświetliły jako jeden rekord dla klienta z określonym przeze mnie id.

Mam taki kod:
SELECT klienci.id, klienci.nazwisko, kredyty.kwota_kredytu, kredyty.id_kredytu FROM klienci, kredyty WHERE kredyty.id_klienta='(tu numer kilienta dla ktorego ma zostac wyswietlony rekord)'"


Ale to rozwiązanie nie działa...

Czy ktoś wie jak skonstruować to zapytanie lub jakieś inne ma rozwiązanie?

konto usunięte

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

SELECT
klienci.id
, klienci.nazwisko
, kredyty.kwota_kredytu
, kredyty.id_kredytu
FROM klienci join kredyty on klienci.id = kredyty.id_klienta
WHERE kredyty.id_klienta = 5
Marcin K.

Marcin K. Java Developer

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

jeżeli we frazie WHERE sprawdzamy id klienta to lepiej zrobić na tabeli, która jest wyciągana bezpośrednio z FROM:

WHERE klienci.id = 5 zamiast WHERE kredyty.id_klienta = 5

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

się podczepie:

nie rozumiem za bardzo czemu dla dwóch takich tabel:


Obrazek


INSERT into kraje (id_kraju,kr_nazwa) VALUES
(SELECT ipcntr,cntr_name
FROM nowa GROUP BY ipcntr)

podawane w PHPMyAdmin nie działa.

Nie to narzedzie, czy nie ten silnik bazy?

Jak włożyć wynik zapytania do innej tabeli w tej samej bazie?

Trzeba wyciągnąc wyniki na zewnatrz i w pętlki ponownie włożyć?

DziękujePaweł P. edytował(a) ten post dnia 22.02.11 o godzinie 20:04
Łukasz Kurowski

Łukasz Kurowski Usque Ad Finem

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

Paweł P.:
INSERT into kraje (id_kraju,kr_nazwa) VALUES
(SELECT ipcntr,cntr_name
FROM nowa GROUP BY ipcntr)

podawane w PHPMyAdmin nie działa.

INSERT into kraje
(SELECT ipcntr,cntr_name
FROM nowa GROUP BY ipcntr)

To powinno zadziałać.
Mariusz Sucajtys

Mariusz Sucajtys Wszyscy wiedzą, że
czegoś nie da się
zrobić, aż znajdzie
...

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

Jest tak, jak napisał Łukasz zgodnie z dokumentacją. Ja ze swojej strony dodam, że warto podać nazwy kolumn, dla których robimy insert

INSERT into kraje (id_kraju,kr_nazwa)
SELECT ipcntr,cntr_name
FROM nowa GROUP BY ipcntr

Nie wiem, po co dodajesz GROUP BY. Jeżeli chcesz wyciągnąć nazwy listę unikatowych par (ipcntr,cntr_name), lepiej użyć słowa kluczowego DISTINCT:

SELECT DISTINCT ipcntr,cntr_name
FROM nowa
Grzegorz D.

Grzegorz D. PL/SQL Developer

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

Mariusz Sucajtys:
Nie wiem, po co dodajesz GROUP BY. Jeżeli chcesz wyciągnąć nazwy listę unikatowych par (ipcntr,cntr_name), lepiej użyć słowa kluczowego DISTINCT:

SELECT DISTINCT ipcntr,cntr_name
FROM nowa

czemu lepiej?
Mariusz Sucajtys

Mariusz Sucajtys Wszyscy wiedzą, że
czegoś nie da się
zrobić, aż znajdzie
...

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

Grzegorz Drzymała:
czemu lepiej?
Bo ma lepszy query plan. Podam na przykładach.
Dane w tabeli

select host_id, id_status from report where host_id = 4;
+---------+-----------+
| host_id | id_status |
+---------+-----------+
| 4 | 5 |
| 4 | 5 |
| 4 | 5 |
+---------+-----------+
3 rows in set (0.00 sec)


Użycie GROUP BY

select host_id, id_status from report where host_id = 4 group by id_status;
+---------+-----------+
| host_id | id_status |
+---------+-----------+
| 4 | 5 |
+---------+-----------+
1 row in set (0.00 sec)
explain select host_id, id_status from report where host_id = 4 group by id_status;
+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+----------------------------------------------+
| 1 | SIMPLE | report | ref | fk_report_hosts | fk_report_hosts | 4 | const | 23 | Using where; Using temporary; Using filesort |
+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+----------------------------------------------+

Użycie DISTINCT

select distinct host_id, id_status from report where host_id = 4;
+---------+-----------+
| host_id | id_status |
+---------+-----------+
| 4 | 5 |
+---------+-----------+
1 row in set (0.00 sec)
explain select distinct host_id, id_status from report where host_id = 4;
+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+------------------------------+
| 1 | SIMPLE | report | ref | fk_report_hosts | fk_report_hosts | 4 | const | 23 | Using where; Using temporary |
+----+-------------+--------+------+-----------------+-----------------+---------+-------+------+------------------------------+


Oba Query wymagają utworzenia tabeli tymczasowej, która prawdopodobnie zmieści się w pamięci. Jednak w przypadku GROUP BY używany jest dodatkowo filesort, co oznacza sortowanie tymczasowej tabeli bez wykorzystania indeksów, których nie posiada. Nie jest to efektywne dla większych tabel. W przypadku DISTINCT ten krok jest pomijany (tabela użyta w przykładzie ma indeks zarówno na host_id, jak i na id_stauts).

Poza tym jest to bardziej intuicyjne dla osoby czytającej kod. W przypadku użycia GROUP BY efektem ubocznym jest wyświetlenie unikatowych par rekordów. Użycie DISTINCT wskazuje jasno, że chcemy otrzymać unikatowe pary rekordów (ipcntr, cntr_name).
Grzegorz D.

Grzegorz D. PL/SQL Developer

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

Wydaje mi się, że opisałeś trochę inny przypadek.
Prosiłem o wytłumaczenie czym różni się

SELECT DISTINCT kol1,kol2,kol3,kol4
FROM tabela

od

SELECT kol1,kol2,kol3,kol4
FROM tabela
GROUP BY kol1,kol2,kol3,kol4

Nigdzie póki co nie było mowy o ograniczaniu zbioru poprzez WHERE. Również ten MySQLowy wynalazek, który pozwala na zawarcie w SELECT kolumn, których nie ma w GROUP BY mnie nie przekonuje...w innych RDBMSach może rodzić problemy.

Edit:
Trochę rozszerzyłem przykład - dodałem dodatkowe wiersze.
Teraz liczba wierszy w tabeli to 103, a liczby unikalnych par 100.

Przykładowo w Oraclu

SQL> set autot trace exp stat
SQL> select host_id, id_status from report group by host_id,id_status;

100 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1613452457

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 103 | 412 | 3 (34)| 00:00:01 |
| 1 | HASH GROUP BY | | 103 | 412 | 3 (34)| 00:00:01 |
| 2 | TABLE ACCESS FULL| REPORT | 103 | 412 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
2036 bytes sent via SQL*Net to client
450 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
100 rows processed

SQL> select distinct host_id, id_status from report;

100 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 2971324893

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 103 | 412 | 3 (34)| 00:00:01 |
| 1 | HASH UNIQUE | | 103 | 412 | 3 (34)| 00:00:01 |
| 2 | TABLE ACCESS FULL| REPORT | 103 | 412 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
2036 bytes sent via SQL*Net to client
450 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
100 rows processed

SQL> select distinct host_id, id_status from report where host_id = 4;


Execution Plan
----------------------------------------------------------
Plan hash value: 3172873005

--------------------------------------------------------------------------------

---------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T

ime |

--------------------------------------------------------------------------------

---------

| 0 | SELECT STATEMENT | | 1 | 4 | 3 (34)| 0

0:00:01 |

| 1 | HASH UNIQUE | | 1 | 4 | 3 (34)| 0

0:00:01 |

| 2 | TABLE ACCESS BY INDEX ROWID| REPORT | 1 | 4 | 2 (0)| 0

0:00:01 |

|* 3 | INDEX RANGE SCAN | IDX_HOST | 1 | | 1 (0)| 0

0:00:01 |

--------------------------------------------------------------------------------

---------


Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("HOST_ID"=4)


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
472 bytes sent via SQL*Net to client
384 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> select host_id, id_status from report where host_id = 4 group by host_id, id_status;


Execution Plan
----------------------------------------------------------
Plan hash value: 3010188360

--------------------------------------------------------------------------------

---------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T

ime |

--------------------------------------------------------------------------------

---------

| 0 | SELECT STATEMENT | | 1 | 4 | 3 (34)| 0

0:00:01 |

| 1 | HASH GROUP BY | | 1 | 4 | 3 (34)| 0

0:00:01 |

| 2 | TABLE ACCESS BY INDEX ROWID| REPORT | 1 | 4 | 2 (0)| 0

0:00:01 |

|* 3 | INDEX RANGE SCAN | IDX_HOST | 1 | | 1 (0)| 0

0:00:01 |

--------------------------------------------------------------------------------

---------


Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("HOST_ID"=4)


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
472 bytes sent via SQL*Net to client
384 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed



HASH GROUP BY i HASH UNIQUE są z tego co wiem równoważne.
Nie widzę więc różnicy w zastosowaniu DISTINCT/GROUP BY.

PozdrawiamGrzegorz Drzymała edytował(a) ten post dnia 23.02.11 o godzinie 12:23
Mariusz Sucajtys

Mariusz Sucajtys Wszyscy wiedzą, że
czegoś nie da się
zrobić, aż znajdzie
...

Temat: mySQL -pobieranie danych z wielu tabel dla jednego...

Grzegorz Drzymała:
Wydaje mi się, że opisałeś trochę inny przypadek.
Prosiłem o wytłumaczenie czym różni się

SELECT DISTINCT kol1,kol2,kol3,kol4
FROM tabela

od

SELECT kol1,kol2,kol3,kol4
FROM tabela
GROUP BY kol1,kol2,kol3,kol4

Nigdzie póki co nie było mowy o ograniczaniu zbioru poprzez WHERE. Również ten MySQLowy wynalazek, który pozwala na zawarcie w SELECT kolumn, których nie ma w GROUP BY mnie nie przekonuje...w innych RDBMSach może rodzić problemy.
Prosiłeś o wytłumaczenie, i wytłumaczyłem: w MySQL użycie DISTINCT daje lepszy query plan. W oryginalnym zapytaniu użyłem WHERE, ponieważ nie chciałem preparować specjalnej tabeli do testów i tabela, na której robiłem testy ma ok. 100mln rekordów.

Wrzucam więc query plan bez WHERE na tej samej tabeli bez wykonania zapytań ze względu na wspomnianą liczbę rekordów(przewidywana liczba wyników dla tego zapytania to ok. 4mln):

mysql> explain select host_id, id_status from report group by host_id, id_status;
+----+-------------+--------+------+---------------+------+---------+------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+-------+---------------------------------+
| 1 | SIMPLE | report | ALL | NULL | NULL | NULL | NULL | 27674 | Using temporary; Using filesort |
+----+-------------+--------+------+---------------+------+---------+------+-------+---------------------------------+

mysql> explain select distinct host_id, id_status from report;
+----+-------------+--------+------+---------------+------+---------+------+-------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+-------+-----------------+
| 1 | SIMPLE | report | ALL | NULL | NULL | NULL | NULL | 27674 | Using temporary |
+----+-------------+--------+------+---------------+------+---------+------+-------+-----------------+

Query plan bez WHEREnie różni się niczym z punktu widzenia planera zapytań w MySQL, w kolumnie Extra nie pojawia się tylko informacja Using where. W stosunku do poprzedniego planu z wykorzystaniem WHERE jest jeszcze jedna różnica: zapytanie nie wykorzystuje indeksów, ponieważ nie ma WHERE i jest wykonywany Full table scan.
Mój przykład z użyciem WHERE zobrazował różnicę pomiędzy dwoma typami zapytań w MySQL.
Trochę rozszerzyłem przykład - dodałem dodatkowe wiersze.
Teraz liczba wierszy w tabeli to 103, a liczby unikalnych par 100.

Przykładowo w Oraclu
Zarzuciłeś mi, że opisuję inny przypadek, po czym sam opisałeś coś zupełnie innego. Pytanie dotyczyło bazy danych MySQL, a ty opisujesz różnice w wykonaniach 2 typów zapytań w Oracle. Jeżeli w Oracle oba zapytania mają taki sam koszt, to tylko plus dla Oracle.
W MySQL, którego dotyczy ten wątek jednak jest inaczej, i zwróciłem na to uwagę. Zapytanie z GROUP BY wymaga dodatkowego sortowania tabeli tymczasowej. Więcej w dokumentacji do EXPLAIN.Mariusz Sucajtys edytował(a) ten post dnia 06.03.11 o godzinie 23:02

Następna dyskusja:

MySQL. Dodawanie danych los...




Wyślij zaproszenie do