[MySQL] Variablen durch SELECT Abfrage definieren

Steusi

Nasenbär

Hallo Leute,

ich habe bei mir einige Bestelldaten. Da gibt es ein Feld Positionen, welche ich als TinyInt laufen hatte. Nun gibt es doch tatsächliche einige Bestellungen, die mehr als 127 Positionen haben. Also habe ich die Spalte in Int geändert, nur muss ich auch noch die fehlerhaften Datensätze reparieren :)

Nun kommt es zu meiner Frage, wie kann ich korrekt Variablen deklarieren?
SET, DECLARE, einfach durch := ?

Ich möchte in soetwas realisieren:

SQL:
@start = (SELECT ID 
	  FROM data  	
	  WHERE order_pos = 126
	  AND order_id = '######')

@dif = (SELECT (ID-order_pos) as dif 
        FROM data 
        WHERE ID = @start)

@end = @start +2 + (SELECT COUNT(ID) 
		    FROM data
		    WHERE order_pos = 127 
		    AND order_id = '######')

UPDATE data SET order_pos = (ID-@dif)
WHERE ID >= @start +2 
AND ID <= @end

Geht soetwas?
Kann ich es so über PHPMyAdmin eingeben? Es betrifft nur 10 Bestellungen, sodass ich die '######' fix selbst setze :)

Würde mich über einen Tipp sehr freuen :)

DANKE


//edit:
Da es ab morgen laufen muss habe ich es erstmal fix mit PHP gemacht eben. Würde trotzdem gern wissen, wie man soetwas in reinem SQL realisiert. Läuft soetwas über Prozeduren?

Vielleicht hilft der PHP-Code ja zum Verständnis:
PHP:
require("../lib/dbconnect.inc.php");

function do_qry($statement,$debug = true){
    $error = substr($statement,0,6);

    $ergo = mysql_query($statement);

    if(mysql_error() && $debug == true){
        echo($error."-Fehler:<br>".mysql_errno()." <b>".mysql_error()."</b><p>");
    }

    return $ergo;
}

$sql_orderid_qry = "SELECT `order_id`,order_line_item_id, COUNT(ID) as anz 
                    FROM `data` 
                    WHERE `order_line_item_id` = 127 
                    GROUP BY order_line_item_id, `order_id` 
                    HAVING anz > 1";

$sql_orderid = do_qry($sql_orderid_qry);

while($row = mysql_fetch_object($sql_orderid)){

    $sql_start_qry = "SELECT ID 
                    FROM data     
                    WHERE order_line_item_id = 126
                    AND order_id = '{$row->order_id}'";

    $start = mysql_fetch_object(do_qry($sql_start_qry))->ID;


    $sql_dif_qry = "SELECT (ID - order_line_item_id) AS dif 
                    FROM data 
                    WHERE ID = {$start}";

    $dif = mysql_fetch_object(do_qry($sql_dif_qry))->dif;


    $sql_end_qry = "SELECT COUNT(ID) as anz
                    FROM data
                    WHERE order_line_item_id = 127 
                    AND order_id = '{$row->order_id}'";

    $end = mysql_fetch_object(do_qry($sql_end_qry))->anz;

    $b1 = $start +2;         
    $b2 = $start + $end;

    $sql_fix_qry = "UPDATE data SET order_line_item_id = (ID-$dif)
                    WHERE ID >= {$b1}
                    AND ID <= {$b2}";

    do_qry($sql_fix_qry);    
    
}
 
Zuletzt bearbeitet von einem Moderator:
Es gibt da sicher eine Lösung. Aber ich versteh nicht was das ganze soll. Der Anfang ist klar. Du suchst alle Beiträge die in der Gruppe mehrere male mit der order_line_item_id=127 auftauchen.

Aber nachher mischst und zählst du diverse verschiedene ID-Felder miteinander.

Aber so auf die schnelle:
item:
In @start nimmst du die ID von Einträge mit der order_line_item_id = 126. Für @dif nimmst du diejenigen. welche die @start als ID haben und zählst davon order_line_item_id ab - und das ist somit immer 126.
Daraus ergibt sich für @start und @dif
SQL:
SELECT
	id+2		AS start_id,
	id-126 	AS dif
FROM
	mydata
WHERE
	order_line_item_id = 126
	AND order_id = @order_id;

item:
Du Filterst mit dem ersten Query alle betroffenen Datensätze. Dazu prüfst du die Anzahl ID auf order_line_item_id=127.
Später nimmst du die entsprechende order_id und order_line_item_id=127 und suchst damit die Anzahl Einträge. Auch das geht in einem:
SQL:
		SELECT 
			order_id,
			COUNT(id) AS anz
		FROM 
			my_data 
		WHERE 
			order_line_item_id = 127 
		GROUP BY 
			order_id
		HAVING 
			anz > 1;

item:
Anstelle von <= und => können wir doch gleich BETWEEN verwenden




Dann können wir alles in ein einziges SELECT quetschen. Variablen sind hier eher hinderlich.

Hier mal das ganze noch als SELECT. Ist besser zum prüfen was rauskommen täte.
SQL:
SELECT
	my_data.id							AS orig_id,
	my_data.id - start_data.dif   AS new_id
FROM
	-- Quelle
	my_data,
	-- Eingrenzung auf alle wo mehrere 127er existieren. Zudem ermitteln der Anzahl
	(
		SELECT 
			order_id,
			COUNT(id) AS anz
		FROM 
			my_data 
		WHERE 
			order_line_item_id = 127 
		GROUP BY 
			order_id
		HAVING 
			anz > 1
	) AS selection,
	-- Ermitteln der start_id und der differenz
	(
		SELECT
			id+2		AS start_id,
			id-126 	AS dif
		FROM
			my_data
		WHERE
			order_line_item_id = 126
	) AS start_data
WHERE
	selection.order_id = my_data.order_id,
	AND selection.order_id = start_data.order_id
	AND my_data.id BETWEEN start_data.start_id AND (start_data.start_id + selection.anz);

Und das ganze noch in ein Update quetschen - müsste ungefähr so aussehen
SQL:
UPDATE
	my_data,
	(
		SELECT 
			order_id,
			COUNT(id) AS anz
		FROM 
			my_data 
		WHERE 
			order_line_item_id = 127 
		GROUP BY 
			order_id
		HAVING 
			anz > 1
	) AS selection,
	(
		SELECT
			id+2		AS start_id,
			id-126 	AS dif
		FROM
			my_data
		WHERE
			order_line_item_id = 126
	) AS start_data
SET
	my_data.id	=	my_data.id - start_data.dif
WHERE
	selection.order_id = my_data.order_id,
	AND selection.order_id = start_data.order_id
	AND my_data.id BETWEEN start_data.start_id AND (start_data.start_id + selection.anz);


Alles natürlich wie immer ungeprüft
 
Zuletzt bearbeitet von einem Moderator:
Danke Yaslaw, wie immer genieal dein Lösungsvorschlag.
Das Update auch mit "virtuellen Tabellen" (Also mit einem Select daunter, so wie du es beschrieben hast klar kommt, ist mir neu :) - wieder was dazugelernt)

Vielen Dank für die ausführliche Beschreibung!
 
Das sind keine Virtuellen Tabellen - das sind Subqueries.
Eine Virtuelle Tabelle sieht eher so aus
SQL:
SELECT
  my_table.*
FROM
  (
    -- Virtuelle Tabelle als Subquery
    SELECT 'A1' AS a, 'B1' AS b
    UNION SELECT 'A2' AS a, 'B2' AS b
    UNION SELECT 'A3' AS a, 'B3' AS b
  ) AS my_table
WHERE
  my_table.a = 'A2'
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück