Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Select-Abfrage mit variablem Spaltennamen

Die einfachste Lösung besteht darin, zwei separate Abfragen zu verwenden.

Wir verwenden das Ergebnis der ersten Abfrage, um den SQL-Text für die zweite Abfrage dynamisch zu generieren.

mysql> SET @colname := '' ; 
mysql> SELECT t.rslt FROM table1 t WHERE t.id = 1 ORDER BY t.rslt LIMIT 1 INTO @colname ;

mysql> SET @sql := CONCAT('SELECT `',@colname,'` FROM table2 ORDER BY 1') ;
mysql> PREPARE stmt FROM @sql ; 
mysql> EXECUTE stmt ;

mysql> DEALLOCATE PREPARE stmt ;

Hinweis:einschließlich @colname Als Teil des SQL-Textes ist dynamisch vorbereitetes SQL eine potenzielle SQL-Injection-Schwachstelle.

Wenn die Anforderung darin besteht, etwas Ähnliches im Rahmen einer Single zu erledigen SQL-Anweisung, dann muss die Anweisung die möglichen Werte antizipieren, die für die Abfrage von Tabelle1 zurückgegeben werden sollen, und explizite Verweise auf die möglichen Spalten von Tabelle2 enthalten. Zum Beispiel so etwas:

  SELECT CASE ( SELECT t.rslt FROM table1 t WHERE t.id = 1 LIMIT 1 )
           WHEN 'r1' THEN r.r1 
           WHEN 'r2' THEN r.r2 
           WHEN 'r3' THEN r.r3 
           ELSE NULL
         END AS c2
    FROM table2 r
   ORDER BY ...

Dies ist nicht unbedingt die effizienteste Art, die Abfrage zu schreiben, aber es demonstriert das Muster.

Innerhalb einer SQL-Anweisung müssen die Bezeichner (Tabellennamen, Spaltennamen, Funktionsnamen) explizit angegeben werden; diese können zur Laufzeit nicht dynamisch abgeleitet werden. Das liegt an der Art und Weise, wie SQL-Anweisungen verarbeitet werden... Analysieren des SQL-Texts auf Syntax, dann Analysieren auf Semantik (gültige Referenzen und Privilegien), Bewerten der relativen Kosten für verfügbare Zugriffspfade, Auswählen eines Ausführungsplans und dann Ausführen dieses Plans.

Das heißt, das bei diesem SQL beobachtete Verhalten ist das, was wir erwarten:

 SELECT (SELECT rslt FROM table1 WHERE id = 1) FROM table2

Der SQL-Text wird vorbereitet und zur Ausführungszeit für jede Zeile in Tabelle2, die Unterabfrage in SELECT Liste wird ausgeführt. Wenn die Unterabfrage einen Skalarwert zurückgibt, wird der Skalarwert als Spalte der äußeren Abfrage zurückgegeben. Der von der Unterabfrage zurückgegebene Wert ist ein Wert , wird (und kann) nicht als Spaltenname ausgewertet.