Van egy adatbázis, amin belül van egy 'cégek' tábla, ami tartalmazza a cégek főbb adatait. Minden cégnek van egy külön 'CÉGNEVE_országok' táblája, amiben a hozzá kapcsolódó országok paraméterei szerepelnek.
Azt szeretném elérni, hogy az összes 'CÉGNEVE_országok' táblából olvassa ki az országok neveit, hogy azt egy legördülő listában jelenítsem meg, így az adott országhoz tartozó cégeket akarom majd kiíratni.
Próbálkoztam sokféleképp, a megoldáshoz legközelebb talán ezzel jutottam:
SELECT *
FROM (SELECT GROUP_CONCAT( table_name )
FROM information_schema.tables
WHERE table_schema = 'adatbazis' AND table_name LIKE '%_orszagok'
) AS x
A belső SELECT szépen kidobja az érintett táblák vesszővel elválasztott listáját, de a külső SELECT-et nem tudom rávenni arra, hogy ebből a listából vegye a táblák neveit, és ne ennek a listának az elemeit (azaz egy darab sztringet) akarjon kiírni.
Rossz úton járok, vagy csak még nem találtam meg a megfelelő utasítást?
- 5567 megtekintés
Hozzászólások
Ha az emlékeim nem csalnak, akkor ezt csak tárolt eljárással tudod megoldani.
A from után írt select arra való, hogy a külső select annak az eredményéből válogasson.
- A hozzászóláshoz be kell jelentkezni
elõször a PREPARE statement jutott eszembe, de táblanévnek nem fogad el változót.
ezzel a trükkel viszont igen:
http://dev.af83.com/2007/05/30/use-parameters-for-field-and-table-names…
~~~~~~~~
deb http://deb.metaltux.tk/ wheezy testing
- A hozzászóláshoz be kell jelentkezni
várj, te ugye nem SELECT *-ot akarsz? ahhoz össze kéne kapcsolni a táblákat. de még nem is SELECT orszag FROM ceg1_orszagok, ceg2_orszagok;
~~~~~~~~
deb http://deb.metaltux.tk/ wheezy testing
- A hozzászóláshoz be kell jelentkezni
Ha az %_orszagok táblákban azonosak az oszlopok:
create view ORSZAGOK AS
select 'CEG1' CEGNEV, * from CEG1_ORSZAGOK
union
select 'CEG2' CEGNEV, * from CEG2_ORSZAGOK
....
union
select 'CEGX' CEGNEV, * from CEGX_ORSZAGOK;
A fent létrejött view-ból ízlés szerint szelektálgathatsz.
Amúgy ezt a %_orszagok jellegű particionálást el kellene felejteni (ha van rá lehetőség), mert elbonyolítja az alkalmazást, mint a mellékelt ábra is mutatja.
- A hozzászóláshoz be kell jelentkezni
itt van egy eljárás tetszõleges számú %\_orszagok táblára
create temporary table tmp1 (orszag varchar(64));
DELIMITER //
CREATE PROCEDURE proc1()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE tbl VARCHAR(32);
DECLARE cur1 CURSOR FOR SELECT table_name from information_schema.tables where table_schema = 'adatbazis' and table_name like '%\_orszagok';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO tbl;
IF done THEN
LEAVE read_loop;
END IF;
SELECT CONCAT("insert into tmp1 select orszag from ", tbl) INTO @stmt;
PREPARE stmt1 FROM @stmt;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END LOOP;
CLOSE cur1;
END
//
DELIMITER ;
SELECT orszag FROM tmp1;
mindazonáltal csatlakozom az elõttem szólóhoz, szuboptimális ez a db szervezés, illetve ha lehet, inkább szkriptbõl (php) ciklussal, több sql queryvel állítani össze a listát.
~~~~~~~~
deb http://deb.metaltux.tk/ wheezy testing
- A hozzászóláshoz be kell jelentkezni
Élmény lesz ezzel a struktúrával komplexebb lekérdezéseket írni... hát még kódot folyamatosan karbantartani.
- A hozzászóláshoz be kell jelentkezni
Köszönöm szépen a válaszokat!
Miután megírtam a kérdést, kb. 10 perce rá koppant, hogy (mivel php-ban használom) két külön lekérdezéssel lehet csak megoldani anélkül, hogy túlbonyolított sql utasításokkal rabolnám a saját időmet... (-_-')
Mindenesetre már csak tiszteletből is áttanulmányozom a válaszként írt kódokat.
Ha nem így, akkor miként kellene megoldani, hogy minden cég adatai külön-külön vezetve legyenek? Miért baj, ha 'CÉGNEVE_országok'-ban tárolom a hozzá tartozó országok paramétereit? Vagy csak a LIKE '%_orszagok' a hülyeség?
--
A kényszer helyett a tudásvágy vezessen a tanulásban!
- A hozzászóláshoz be kell jelentkezni
Tábla (ojjektum) _nevében_ nem tárolunk adatot. Márpedig te most ezt teszed. (Ne kössön bele senki, hogy a táblanév is adat! Vagy ha mégis, akkor fogalmazza meg pontosabban! :) )
- A hozzászóláshoz be kell jelentkezni
Ok, de akkor milyen azonosítót adjak neki? SHA? Egyébként miért nem használjuk azonosításra? Ha nem jut eszembe mondjuk az egyik tábla neve, akkor SHOW TABLE-ben könnyebben eligazodok az emberi neveken.
--
A kényszer helyett a tudásvágy vezessen a tanulásban!
- A hozzászóláshoz be kell jelentkezni
Nem akarlak tévútra vinni. Azt hiszem, adat (bázis) normalizálás a kulcsszó. A cégneveket, országok neveit ú.n. szótár táblákban szokás tárolni. De már annyira leépültem a nagy semmittevésben, hogy jobban jársz, ha bővebben valaki hozzáértő mesél róla.
Azt meg remélem, nem értettem félre, hogy most valami ilyen táblaneveket használsz:
ibm_hungary
microsoft_usa
stb.
Ha nem ezt csináltad, akkor részemről félreértés az egész.
- A hozzászóláshoz be kell jelentkezni
Ha neked országonként kellenek adatok, akkor egyszerűen a rekordodban tárolod az országot - számkóddal, 2-/3-betűsen, teljes névvel, mindegy, ha konzisztens -, és az SQL-eid where/group by/having/order by részében szerepelteted a megfelelő kódokat.
Ha az adatbázismotorod támogatja a táblapartícionálást, így is izolálhatók az országdimenziók, de azt sejtem, nem a te rekordvolumened az, ahol erre szükség van.
Sokkal inkább szükség van az országot jelképező mező felvételébe minden olyan indexkulcsba, amely a fenti SQL-mondatrészeket támogatni képes.
"Egyébként miért nem használjuk azonosításra?"
Mert az adatbázisokból/-ba kódok szoktak dolgozni, amelyek természete az, hogy változnak - akár azért, mert az alapkoncepció volt téves, akár az igények változása miatt. Míg ma talán az az elvárás, hogy összesítéseket országonként kell adnod, holnap egy komplex, globális igény megizzaszthat, vagy csak felesleges iterációra késztet. És ez még hagyján, mert ennél messze kellemetlenebb, ha táblaváltoztatást/adatkarbantartást/törlést/migrációt kell végrehajtanod. Egy tábla (+segédtáblái, ha tovább van az adathalmaz normalizálva) feltételes műveletei helyett gányolásba torkollik a munka.
Érdemes szem előtt tartani azt, hogy az adatbáziskezelők létrehozásának egyik célja volt a kód logikájának és az adatok (manipulálásának) szétválasztása. Ha te táblaneveket dinamikusan generálsz, mert a logika függvénye a sok ugyanolyan tartalmú tábla közül a szükséges, akkor ezzel szembe mész.
- A hozzászóláshoz be kell jelentkezni
adatbáziskezelés alapok.
olyasminek nézz utána, hogy normalizálás, 2nf, 3nf, bcnf, kapcsoló tábla.
itt kb az kell, hogy:
cegek: id, nev
orszag: id, nev
ceg_orszag: ceg_id, orszag_id
és kb. ennyi.
összes orszag_id kigyűjtése:
select distinct orszag_id from ceg_orszag
--
Gábriel Ákos
http://i-logic.hu
- A hozzászóláshoz be kell jelentkezni
ja és még egy: ha normális sql-t akarsz tanulni, akkor ne pont mysql-t használj, hanem sokkal inkább postgresql-t.
vagy akár oracle_xe-t, az is free.
a mysql-en majd ráész szörnyülködni később, ha muszáj lesz szívni vele.
--
Gábriel Ákos
http://i-logic.hu
- A hozzászóláshoz be kell jelentkezni
Azt hiszem kezdem érteni a dolgot. Eddig kb. így nézett ki az adatbázis:
CÉGEK
-----
egyik_cég egyik_adat másik_adat
másik_cég egyik_adat másik_adat
...
EGYIK_CÉG_ORSZÁGOK
------------------
H egyik_adat másik_adat
D egyik_adat másik_adat
USA egyik_adat másik_adat
MÁSIK_CÉG_ORSZÁGOK
------------------
CZ egyik_adat másik_adat
H egyik_adat másik_adat
SK egyik_adat másik_adat
Ha jól értem, akkor ezt ilyen formába kellene konvertálni:
CÉGEK
-----
egyik_cég H,USA,D egyik_adat másik_adat
másik_cég H,CZ,SK egyik_adat másik_adat
...
ORSZÁGOK
------------------
CZ másik_cég egyik_adat másik_adat
D egyik_cég egyik_adat másik_adat
H egyik_cég egyik_adat másik_adat
H másik_cég egyik_adat másik_adat
SK másik_cég egyik_adat másik_adat
USA egyik_cég egyik_adat másik_adat
Ha a céghez tartozó országokat akarom lekérdzeni, akkor kb. azt mondom, hogy 'válaszd ki az orzágokból azokat, amelyek a céghez vannak rendelve'. (persze a cég neve helyett egy id-vel kötöm össze őket)
Ami azt illeti így valóban egyszerűbbnek tűnik, az országok listája is egy pillanat alatt megvan egy lekérdezésből (az eddigi kettő helyett), azt hiszem ennél a megoldásnál maradok.
Köszönöm a segítségeteket!
--
A kényszer helyett a tudásvágy vezessen a tanulásban!
- A hozzászóláshoz be kell jelentkezni
még visszább az alapokhoz, tessék megtanulni mi az a mező, mi tartozik egy mezőbe és mi nem.
országok neveit nem rakjuk egymás mellé vesszővel elválasztva.
ne sajnáld az adatbázist, ez nem excel, nincs miért spórolni a sorokkal.
--
Gábriel Ákos
http://i-logic.hu
- A hozzászóláshoz be kell jelentkezni
Csatlakozom az előttem szólóhoz:
A cégek és az országok között M:N típusú kapcsolat van, tehát un. "kapcsolótábla" a szokásos megoldás erre a problémára.
- A hozzászóláshoz be kell jelentkezni
Vagy az alkalmazás kedvéért denormalizálod a táblát. Persze ez függ az adatok milyenségétől is. De az a megérzésem (lx egyik hozzászólása alapján), hogy itt megéri.
-----------
"Pontban 0:00-kor nem nagyon szoktak véletlen dolgok történni"
- A hozzászóláshoz be kell jelentkezni
a kérdezőnek imho először érdemes volna megtanulnia bcnf-ben gondolkozni, utána lehet majd azon elmélkedni, hogy mikor veszünk ebből vissza...
--
Gábriel Ákos
http://i-logic.hu
- A hozzászóláshoz be kell jelentkezni