ugrás a tartalomhoz

MySQL egy tábla kapcsolása több rekordhoz

Theo76 · 2016. Május. 30. (H), 09.59
Sziasztok!

Van egy sql táblám. A tábla szerkezete:
tábla neve: kliens
ID
szulhely
varos

Másik tábla:
tábla neve: varos
ID
varosnev

A gondom az, hogy a kliens táblába a szulhely, és varos rekordját kéne összekötnöm a varos táblával. Van erre lehetőség, vagy marad az a megoldás, hogy külön lekérdeztetem?
 
1

Szia! Amit Te keresel, azt

smokey · 2016. Május. 30. (H), 10.27
Szia!

Amit Te keresel, azt idegen kulcsok kezelésének hívják. A kliens táblába kell, hogy legyen egy mező, ami a város táblára hivatkozik, méghozzá egy idegen kulccsal. A kliens táblában nem a város nevét kell letárolnod, hanem, a város táblában szereplő város ID-ját. Első körben a kliens táblában lévő varos mezőt átnevezném varos_id-ra, csak hogy tudd később, hogy ott egy kulcsot tárolsz, nem pedig más értéket

A lekérdezésben, ahol szeretnéd lekérdezni a várost is, JOIN-olnod kell az idegen táblát. Ezt megoldhatod több JOIN típussal is.

Egy nem tesztelt példa INNER JOIN-nal - remélem, hogy működik:

SELECT k.ID, k.szulhely, k.varos, v.varosnev
FROM kliens AS k
INNER JOIN varos AS v ON k.varos_id = v.ID
k => kliens tábla alias
v => varos tábla alias

Ha minden jól megy, akkor egy rekordban vissza kell hogy kapd a kliens összes adatát + a hozzárendelt város nevét is. A listádat tovább tudod szűrni további WHERE feltételekkel, tudod sorba rendezni, stb..
2

köszi szépen. Amit írtál, a

Theo76 · 2016. Május. 30. (H), 12.43
köszi szépen. Amit írtál, a rekordok a kliens táblánál int típusúak, és a város ID-jét tartalmazzák. INNER JOIN-al már próbálkoztam, de csak az első találatot jeleníti meg, nekem viszont ebben az esetben két városnevet kellene visszakapnom.
3

Egy picit elvesztettem a

smokey · 2016. Május. 30. (H), 13.11
Egy picit elvesztettem a fonalat.

Amit írtál, a rekordok a kliens táblánál int típusúak


Eyg rekordnak nem lehet int típusa. Talán a "varos" mezőre gondoltál? Az már lehet int, jobban mondva ugyanaz kell, hogy legyen a típusa, mint a varos tábla ID-mezőjének.

nekem viszont ebben az esetben két városnevet kellene visszakapnom


Nem teljesen értem. Milyen rekordok vannak konkrétan a két táblában? Esetleg le tudnád írni, hogy konkrétan a képernyőre mit szeretnél kiíratni?
4

Így néznek ki konkrétan a

Theo76 · 2016. Május. 30. (H), 13.43
Így néznek ki konkrétan a táblák (a kliensből kivettem azokat a mezőket, amik most feleslegesek):

CREATE TABLE `kliens` (
  `ID` int(11) NOT NULL,
  `szulhely` int(11) NOT NULL,
  `varos` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `varos` (
  `ID` int(11) NOT NULL,
  `irszam` int(11) NOT NULL,
  `varosnev` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
A feladata ami lenne, hogy fel kell vinni egy ügyféllistát születési hellyel, és lakcímmel. A lakcímben a várost külön rekordba tárolom. Mikor lekérdezem az ügyfél adatokat, akkor a kapott adatokba szerepelnie kell a születési helyének, és a lakhelyének is. Gyakorlatilag azt kellene megoldanom, hogy egy táblát kéne két mezőhöz hozzárendelnem:
kliens.szulhely -> varos.varosnev
kliens.varos -> varos.varosnev
5

Ha jól értem, akkor nincs más

smokey · 2016. Május. 30. (H), 15.28
Ha jól értem, akkor nincs más hátra, mint kiegészíteni azt a lekérdezést, amit elküldtem korábban, a JOIN-ok száma nem limitált ;):

SELECT k.ID, k.szulhely, k.varos, vl.varosnev, vsz.varosnev  
FROM kliens AS k  
INNER JOIN varos AS vl ON k.varos = vl.ID  
INNER JOIN varos AS vsz ON k.szulhely = vsz.ID  
Első ránézésre talán működik, második ránézésre viszont nem optimális (nekem legalább is nem tűnik annak). Ha valakinek van tippje, hogy ezt hogyan lehetne jobban megoldani, arra én is kíváncsi volnék, légyszi írjátok majd meg!
6

Nem nagyon egyszerűsíthető

tisch.david · 2016. Május. 30. (H), 23.41
Szia smokey!

Melyik részével vagy elégedetlen? Ilyen egyszerű selectet szerintem nem lehet tovább optimalizálni. Persze egy hajszálnyival egyszerűbben lehetne írni a nem kötelező kulcsszavak kihagyásával, pl. így:
SELECT k.ID, k.szulhely, k.varos, vl.varosnev, vsz.varosnev    
FROM kliens k    
  JOIN varos vl ON k.varos = vl.ID    
  JOIN varos vsz ON k.szulhely = vsz.ID 
De ez csak egy pici rövidítés, nem optimalizálás.

Üdv:
Dávid
7

Hello Dávid, nem vagyok egy

smokey · 2016. Május. 31. (K), 08.16
Hello Dávid,

nem vagyok egy SQL guru, csak haverkodtunk már párszor.. :) Duplikáltnak éreztem a varos tábla joinolását, ezért gondoltam arra, hogy esetleg van szebb megoldás. Köszönöm egyébként a választ!

üdv,
S
9

Mi az egyszerű

Pepita · 2016. Jún. 2. (Cs), 08.55
egy hajszálnyival egyszerűbben lehetne írni

Ez nagyon nézőpont kérdése, hogy kinek mi az egyszerűbb. Ugye itt nem optimalizálásról van szó, a MySQL szervernek mindegy, hogy kiírod-e az INNER-t vagy nem. Azonban egy másik embernek, aki szemmel próbálja elolvasni a lekérdezésedet, semennyit nem segít az, hogy kevesebb karakter, sőt, van akinek pár ms-al több idő így megérteni, mert magában hozzá kell tennie a default join fajtát... :)
8

Igen ez működik :) viszont

Theo76 · 2016. Május. 31. (K), 10.01
Igen ez működik :) viszont ezzel a paranccsal két városnév lesz, amit nem lehet megjeleníteni. Hogy rendesen megjelenjen ki kell egészíteni így:

SELECT k.ID, k.szulhely, k.varos, vl.varosnev AS vl, vsz.varosnev AS vsz
FROM kliens AS k    
INNER JOIN varos AS vl ON k.varos = vl.ID    
INNER JOIN varos AS vsz ON k.szulhely = vsz.ID
Illetve lehet még így:

SELECT kliens.ID, kliens.szulhely, kliens.varos, vl.varosnev AS vl, vsz.varosnev AS vsz
FROM kliens
INNER JOIN varos AS vl ON k.varos = vl.ID    
INNER JOIN varos AS vsz ON k.szulhely = vsz.ID
10

Mindent a nevén

Pepita · 2016. Jún. 2. (Cs), 09.23
Nem parancs, hanem lekérdezés, query. Nagy különbség.
Aztán nagyon nem szerencsés egy query-n belül különböző dolgokra (tábla vs oszlop) azonos alias-al hivatkozni. Ebből hatalmas keveredés és hibák tömege lehet később, amikor "kicsit nagyobb" lekérdezéseket fogsz írni.
Én azt sem tartom feltétlenül jó ötletnek, hogy 1-2 betűs aliasokat használj, lehet pl úgy is, hogy itt a varos táblát kell kétszer "megemlíteni", hát legyen varos1 és varos2.
A második query-ben hiányzik a FROM kliens után a 'k' alias, így a join kapcsolója hibás.
Ha megnézed ezt:
SELECT `kliens`.`ID` AS 'ID', `varos1`.`varosnev` AS 'Varos', `varos2`.`varosnev` AS 'Szuletesi_hely'  
FROM kliens  
INNER JOIN varos AS varos1 ON `kliens`.`varos` = `varos1`.`ID`      
INNER JOIN varos AS varos2 ON `kliens`.`szulhely` = `varos2`.`ID`  
láthatod, hogy nem lett egetverően hosszú, és sokkal olvashatóbb. (+ escape a szükséges helyeken.)
Mindenképpen érdemes egy jó koncepciót követni minden query megírásához, akkor egységes és (legalább számodra) a későbbiekben is átlátható kódod lesz. Ha itt (v bárhol) más külalakban kapsz valami megoldást, azt is mindig "fordítsd le" a saját kocepciód szerint, míg ezt teszed, te is fejlődsz + eszedbe juthatnak még jobb ötletek.