Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Consulta de seleção do MySQL com nome de coluna variável


A solução mais simples é usar duas consultas separadas.

Usamos o resultado da primeira consulta para gerar dinamicamente o texto SQL para a segunda consulta.
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 ;

N.B. incluindo @colname como parte do texto SQL, SQL preparado dinamicamente, é uma vulnerabilidade potencial de SQL Injection.

Se o requisito é fazer algo semelhante no contexto de um único SQL, então a instrução precisa antecipar os possíveis valores a serem retornados para a consulta da tabela1 e incluir referências explícitas às possíveis colunas da tabela2. Por exemplo, algo assim:
  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 ...

Essa não é necessariamente a maneira mais eficiente de escrever a consulta, mas demonstra o padrão.

Dentro de uma instrução SQL, os identificadores (nomes de tabelas, nomes de colunas, nomes de funções) devem ser especificados explicitamente; estes não podem ser derivados dinamicamente em tempo de execução. Isso ocorre por causa de como as instruções SQL são processadas... analisando o texto SQL para sintaxe, depois analisando a semântica (referências e privilégios válidos), avaliando o custo relativo dos caminhos de acesso disponíveis, selecionando um plano de execução e executando esse plano.

Ou seja, o comportamento observado com esse SQL é o que esperamos:
 SELECT (SELECT rslt FROM table1 WHERE id = 1) FROM table2

O texto SQL é preparado e, em tempo de execução, para cada linha na tabela2, a subconsulta no SELECT lista é executada. Se a subconsulta retornar um valor escalar, o valor escalar será retornado como uma coluna da consulta externa. O valor retornado pela subconsulta é um valor , não é (e não pode ser) avaliado como um nome de coluna.