Üdv minenkinek,
Sajnos nem vagyok expert sql szakértő ezért egy kis segítséget szeretnék kérni.
Egy tárolt eljárás készít egy ideiglenes táblát amiből többek között egy lekérdezéssel szeretnék készíteni egy listát.
Ideiglenes tábla szerkezete:
CREATE TEMPORARY TABLE tmptree (
node BIGINT UNSIGNED,
xpos INT UNSIGNED,
ypos INT UNSIGNED
);
A listát gyártó lekérdezés:
SELECT
node AS n,
xpos AS x1,
ypos AS y1,
( SELECT xpos FROM tmptree WHERE node = FLOOR(n/2) ) AS x2,
( SELECT ypos FROM tmptree WHERE node = FLOOR(n/2) ) AS y2,
FROM tmptree ORDER BY y1 DESC;
Ha a lekérdezést lefuttatom akkor a követlező hibaüzenetet kapom:
SQLSTATE[HY000]: General error: 1137 Can't reopen table: 'tmptree'
A dokumentáció szerint azért mert egy lekérdezésen belül nem lehet több hivatkozás ugyanarra az ideiglenes táblára.
http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html
Azt szeretném kérdezni, hogy át lehet valahogy fogalmazni ezt a lekérdezést úgy, hogy ne legyen több hivatkozás a táblára (a két sub-select ne szerepeljen benne)?
A válaszokat előre is köszönöm.
- 4645 megtekintés
Hozzászólások
ez egy csodas mysql feature, aminek "javitasarol" mar ~9 evvel ezelotti levelezesekben is irkaltak mysql fejlesztok.
duplikald a tablat, ha megengedheted magadnak.
--
A gyors gondolat többet ér, mint a gyors mozdulat.
- A hozzászóláshoz be kell jelentkezni
Értem. Akkor tulajdonképpen erősen korlátozott az ideiglenes táblák használhatósága ebből a szemnpontból, mert csak nagyon egyszerű (vagy nagyon trükkösen) megírt lekérdezésekkel lehet használni.
--
maszili
- A hozzászóláshoz be kell jelentkezni
Egy OUTER JOIN nem oldaná meg a problémát? Úgy csak egyszer kell hivatkoznod a táblára.
- A hozzászóláshoz be kell jelentkezni
Sajnos nem tudom. Ez esetben hogyan nézne ki a lekérdezés?
--
maszili
- A hozzászóláshoz be kell jelentkezni
Elnézést, most vettem észre, hogy csak a temp táblát használod, más táblát nem. Ez esetben a join sem segít.
- A hozzászóláshoz be kell jelentkezni
Nálam szabály, hogy a select mező felsorolásába nem teszünk select-et.
Talán ez segít:
select
a.node n
,a.xpos x1
,a.ypos y1
,b.xpos x2
,b.ypos y2
from
tmptree a
left join temptree b
on a.node = b.node * 2
left lehet hogy elhagyható, nem ismerem az adatokat.
- A hozzászóláshoz be kell jelentkezni
A 2. táblareferencia (a self) outer joinnál is a 2. táblareferencia -- ami tilos. Ezen a táblanév elgépelése mint trükk sem segít. :)
- A hozzászóláshoz be kell jelentkezni
Ahaaaa....
Lefelejtettem a hozzászólásból, hogy a mysql "hülyeségeit" nem ismerem, mert még nem használtam komolyabban.
Szóval akkor ne temp táblát használjon. ;)
- A hozzászóláshoz be kell jelentkezni
Én nem tudok más megoldást mint az ideiglenes tábla. A következő okok miatt.
(1) Egy tárolt eljárás készít adatokat (http://hup.hu/node/123399) ahol a feldolgozás során előálló adatok az ideiglenes táblába kerülnek.
Kódrészlet:
INSERT INTO `tmptree` VALUES (`node`,`x`,`y`); /* csomópont kiírása */
(2) Több egyidejű kapcsolat esetén az ideiglenes tábla minden kapcsolat számára egyedi és a különböző kapcsolatok ideiglenes táblái nem zavarják egymást annak ellenére, hogy a lekérdezésben ugyanazzal a névvel hivatkozik rá.
Csak most az a kellemetlen helyzet állt elő, hogy egy lekérdezésen belül csak egy hivatkozás lehet egy ideiglenes táblára. :(
Ezért gondoltam, hogy talán egy nálam okosabb valaki át tudja fogalmazni úgy a lekérdezést, hogy csak egy hivatkozás legyen benne.
--
maszili
- A hozzászóláshoz be kell jelentkezni
Épp akartam kérdezni, hogy mi maga a probléma :-)
Nem lehetne beszúrásnál megadni a mélységet?
- A hozzászóláshoz be kell jelentkezni
A csomópont mélységének meghatározása már megoldott. A tárolt eljárás inorder bejárással végigmegy a részfán (kezdőpont/max mélység) és az ideiglenes táblába készít egy részfát a csomópontok koordinátáival együtt.
Most már ábrázolni kellene a fát grafikusan.
Tahát van egy ideiglenes tábla benne a csomópont azonosítókkal és az x,y koordinátákkal. Így el lehet helyezni a koordináta rendszerben a csomópontokat de a kapcsolatban lévő csomópontok közé vonalat is kellene rajzolni. Ez sem gond mert az aktuális csomópont (x1,y1) lehet a vonal kezdete a vonal vége pedig a szülő csomópont (x2,y2) koordinátája.
Csak itt jön az ideiglenes tábla nyűgje, hogy nem lehet egy lekérdezésen belül több hivatkozás az ideiglebes táblára...
--
maszili
- A hozzászóláshoz be kell jelentkezni
graphviz miért nem jó erre?
https://graphviz-dev.appspot.com/ <-- itt tudsz kipróbálgatni, telepített graphviz nélkül is.
- A hozzászóláshoz be kell jelentkezni
Ezt nem értem. A graphviz megoldja az SQL problémát?
--
maszili
- A hozzászóláshoz be kell jelentkezni
SQL-ből akarja a KÉPET megrajzolni. Ez nem sql feladat.
- A hozzászóláshoz be kell jelentkezni
Az én értem, csak abban nem vagyok biztos, hogy abból az sql táblából ami a fát tárolja a graphviz kultúráltan meg tudja rajzolni a fa részletet. Ha nem akkor meg nagyjából ugyanott vagyok, miszerint az sql adatokból olyan adatokat kell készíteni amit megeszik a graphviz.
--
maszili
- A hozzászóláshoz be kell jelentkezni
Mert ugyanugy le kell gyujteni a temp tablabol az adatokat a graphviznek?
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
láttál már graphvizt?
ha igen: ne trollkodj.
ha nem: a graphviz az A node -> B node kapcsolati listából magának felépíti a gráfot és az elképzeléseidnek megfelelően képre viszi azt.
Mivel a topicnyitónak megvan a gráf, s csak a rajzolását akarja sql-ből megoldani, mindenképp előrébb lenne ezzel.
- A hozzászóláshoz be kell jelentkezni
Lattam mar graphviz-t, csak nem ertettem, mire gondolsz. Igy mar ertem, koszi.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
Es ha... khm... "normalis" tablat hasznalnal, akkor mi tortenne? Normalis alatt a CREATE TABLE tipusu tablat ertem. A vegen el lehetne dobni.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
És azt hogyan oldom meg, hogy a párhuzamos mysql kapcsolatok ne rontsák szét egymás tábláját?
Mert ha józsibácsi készíttet egy fa részletet miközben marinéni is és a programkód meg ugyanazzal a táblanévvel hivatkozik a táblára akkor a két párhuzamosan futó programkód szétveri egymás adatát.
Én csak hobby programozó vagyok, nem tudom hogyan szokás az ilyen problémát kultúráltan megoldani?
--
maszili
- A hozzászóláshoz be kell jelentkezni
Felveszel a tábládba egy creator mezőt, amely tartalmazza, hogy józsibácsi, vagy marinéni, és a lekérdezéseidbe mindenhol belegyógyítod, hogy a joinok figyeljenek arra, hogy józsibácsi és marinéni is csak magához nyúljon ne máshoz.
Ekkor még persze minden hívás végén törölni is kell a józsibácsis/marinénis rekordokat, ami ha elmarad, okozhat később kalamajkát, ezért jobb rögtön a creator mellé egy inkrementált mezőt vagy timestampet (itt: seq) is felvenni, és annak a max értékéhez keresni a creator rekordjait.
(És ha eddig erre nem figyeltél volna, indexek legyenek és legyen elemük a seq és creator is.)
- A hozzászóláshoz be kell jelentkezni
Valószínűleg ez a megoldás lesz. Köszi.
--
maszili
- A hozzászóláshoz be kell jelentkezni
Elég "parasztos" megoldás, de.....
CREATE TEMPORARY TABLE temptree AS (SELECT * FROM tmptree )
Ekkor is hápog a selectemre?
- A hozzászóláshoz be kell jelentkezni
Nyílván ha fizikailag (tartalmával együtt) lemásolom az ideiglenes táblát több példányban és azokra történik a hivatkozás akkor nincs gond. De ha csak egy mód van rá akkor a táblamásolósdit szeretném elkeülni.
--
maszili
- A hozzászóláshoz be kell jelentkezni