Can't reopen mysql temporary table

Ü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.

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.

Egy OUTER JOIN nem oldaná meg a problémát? Úgy csak egyszer kell hivatkoznod a táblára.

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.

É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 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

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

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.

É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

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