KlausStein: Query optimieren / mysql 5

Beitrag lesen

Hallo Vinzenz,

Schau Dir an, wie die betreffenden Knoten aussehen:

SELECT

payload,
    lft,
    rgt
FROM
    000node
WHERE
    payload IN (4303, 5290)

  
Hallo Vinzenz,  
  
das habe ich gemacht und das Ergebnis war enttäuschend.  
  
payload  lft   	rgt  
4303 	1318 	1319  
5290 	1318 	1319  
  
  
Das heißt, wir diskutieren gerade unter völlig verzerrter Ausgangslage und ich muss diese erstmal in Ordnung bringen und hoffe, Du greifst mir dabei ein wenig unter die Arme. Ich tue mein Bestes dazu, bin aber garde erstmal etwas gefrsutet, weil mein Nested Set entweder bei der Anlage bzw. bei dessen Fortführung einen Fehler beinhaltet!  
  
Glücklicherweise habe ich mich nicht ausschließlich zu meinem Nested Set verlassen und habe redundant in meiner main-tabelle den parent-Eintrag mitgeschleppt. Vielleicht gelingt es, den Fehlker zu finden und die node-tabelle neu aufzubauen?  
  
Zum Hintergrund: Stell Dir eine Art schwarzes Brett vor, bei dem User sich gegenseitig auf verschiedene Art schreiben oder auf sich reagieren können.  
  
Das ist meine Haupttabelle "main".  
  
MainID|User|Datum    |...|  Eigennummer  |    parent    |Status|...|  
\------+----+---------+---+---------------+--------------+------+---|  
1     +10  +127...   +...+Status-jahr-lfd+Stat-jahr-lfd-+ X1   +...|  
\------+----+---------+---+---------------+--------------+------+---|  
2     +7   +127...   +...+Status-jahr-lfd+Stat-jahr-lfd-+ X4   +...|  
\-------------------------------------------------------------------|  
usw.  
  
Leider führe ich das Datum als timestamp mit. Das Programm ist schon etwas älter, das haben früher wohl viele so gemacht.  
  
Die Eigennummer setzt sich aus dem Status, der 2-stelligen Jahreszahl und einer fortlaufenden Nummer zusammen. Der Status selber besagt nur die Art der Kommunikation.  
  
Dann gibts noch eineige andere Spalten, die aber erstmal weniger interessant sein dürften.  
  
Das Nested Set benötige ich, um eine Art Baumstruktur der Kommunikation herstellen zu können.  
  
Eintrag:  
  
Zum Eintragen rufe ich eine Funktion mit 2 Parametern auf. Einmal der MainID und, falls vorhanden einer ReferenzID, also der MainID eines parent.  
  
In der funktion prüfe ich bei Vorhandensein einer ReferenzID erstmal, ob es einen Vorgang in der node-tabelle mit diesen Daten gibt.  
Ist das der Fall, besorge ich mir die Referenzdaten und mache den Eintrag:  
  
~~~sql
  
$query_node_referenz="select  root_id,lft,rgt  FROM ".tableprefix."node WHERE payload ='$ReferenzID'";  
$result_node_referenz=mysql_query($query_node_referenz);  
if ($result_node_referenz==FALSE)  
     {  
          error(mysql_error(),'','',''); // ja, ich weiß, was nun kommt...  
     }  
$row_node_referenz=mysql_fetch_row($result_node_referenz);  
$V_ROOT_ID=$row_node_referenz[0];  
$V_LFT=$row_node_referenz[1];  
$V_RGT=$row_node_referenz[2];  
  
  
// Und jetzt der neue Eintrag  
$result10=mysql_query("LOCK TABLES '".tableprefix."node' WRITE");  
  
$query_update1="UPDATE ".tableprefix."node  
   SET lft      =  lft + 2  
 WHERE root_id  =  ".$V_ROOT_ID."  
   AND lft      >  ".$V_RGT."  
   AND rgt      >= ".$V_RGT."";  
$result_update1=mysql_query($query_update1);  
  
$query_update2="UPDATE ".tableprefix."node  
   SET rgt      =  rgt + 2  
 WHERE root_id  =  ".$V_ROOT_ID."  
   AND rgt      >= ".$V_RGT."";  
$result_update2=mysql_query($query_update2);  
  
$query2="  
INSERT INTO ".tableprefix."node ( root_id, payload, lft, rgt )  
          VALUES ( $V_ROOT_ID, $MainID, $V_RGT, $V_RGT + 1 )";  
$result12=mysql_query($query2);  
$result13=mysql_query("UNLOCK TABLES");  

Nun der Fall, dass keine ReferenzID übergeben wurde:

Dann scahue ich zuerst nach, ob im lfd. Jahr schon ein Eintrag existiert oder nicht.

Fall 1 (es existiert noch keine):

  
  
$result14=mysql_query("LOCK TABLES '".tableprefix."node' WRITE");  
$query="  
  
INSERT INTO ".tableprefix."node ( payload, lft, rgt )  
          VALUES ( '$Jahr', '1', '2' )";  
$result22=mysql_query($query);  
  
$last_insert_id= mysql_result(mysql_query("SELECT MAX(node_id) FROM ".tableprefix."node"), 0);  
  
$query_update1="UPDATE ".tableprefix."node  
   SET root_id = ".$Jahr."  
 WHERE node_id = ".$last_insert_id."";  
$result_update1=mysql_query($query_update1);  
  
 $query_update2=" UPDATE ".tableprefix."node  
   SET lft      =  lft + 2  
 WHERE root_id  =  ".$Jahr."  
   AND lft      >  2  
   AND rgt      >= 2";  
$result_update2=mysql_query($query_update2);  
  
 $query_update3="  
UPDATE ".tableprefix."node  
   SET rgt      =  rgt + 2  
 WHERE root_id  =  ".$Jahr."  
   AND rgt      >= 2";  
$result_update3=mysql_query($query_update3);  
  
$query2="  
INSERT INTO ".tableprefix."node ( root_id, payload, lft, rgt )  
          VALUES ( $Jahr, $MainID, 2, 3 )";  
		  
$result23=mysql_query($query2);  
$result15=mysql_query("UNLOCK TABLES");  

Fall 2 (es gibt schon > 1 Eintrag in diesem Jahr):

  
// Hierzu erstmal die Referenzdaten des Leereintrag des lfd. Jahres besorgen  
$query_node_referenz="select root_id,lft,rgt  FROM ".tableprefix."node WHERE payload =\"$Jahr\"";  
$result_node_referenz=mysql_query($query_node_referenz);  
if ($result_node_referenz==FALSE)  
     {  
          error(mysql_error(),'','','');  
     }  
$row_node_referenz=mysql_fetch_row($result_node_referenz);  
$V_ROOT_ID=$row_node_referenz[0];  
$V_LFT=$row_node_referenz[1];  
$V_RGT=$row_node_referenz[2];  
  
//################################################  
  
  
// Und jetzt der neue Eintrag  
$result16=mysql_query("LOCK TABLES '".tableprefix."node' WRITE");  
  
$query_update1="UPDATE ".tableprefix."node  
   SET lft      =  lft + 2  
 WHERE root_id  =  ".$V_ROOT_ID."  
   AND lft      >  ".$V_RGT."  
   AND rgt      >= ".$V_RGT."";  
$result_update1=mysql_query($query_update1);  
  
$query_update2="  UPDATE ".tableprefix."node  
   SET rgt      =  rgt + 2  
 WHERE root_id  =  ".$V_ROOT_ID."  
   AND rgt      >= ".$V_RGT."";  
  
$result_update2=mysql_query($query_update2);  
  
$query2="  
INSERT INTO ".tableprefix."node ( root_id, payload, lft, rgt )  
          VALUES ( $V_ROOT_ID, $VorgangsID, $V_RGT, $V_RGT + 1 )";  
$result18=mysql_query($query2);  
$result19=mysql_query("UNLOCK TABLES");  
  

Ich hoffe, ich konnte die Vorgangsweise knapp genug schildern, um keinen damit zu überfordern und ausführlich genug, um eventuelle Fehler aufzudecken.

Übrigens lösche ich keine Datensätze aus der node-tabelle heraus. Die berücksichtige ich später in den Abfragen über ein "delete-flag", dass in der main-Tabelle vorliegt.

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

Siehst Du in der obigen Vorgehensweise den Grund für die ja zweifelsfrei vorhandenen Fehleinträge?

Weil, wenn das alles soweit korrekt wäre, müsste der Fehler in den übergebenen Parametern liegen.

Bis hierher erstmal, danke fürs "Miträtzeln" und freundliche Grüße.

KlausStein