Estou trabalhando em algo e encontrei esse SQL que não tenho certeza de como reescrever corretamente, ou seja, usando PHP PDO.
O SQL se parece com:
$sql = 'SELECT * FROM table WHERE column ' . isset($variable) ? . '=' . $variable : '>0';
Basicamente, o que a consulta está dizendo é: se $variable
estiver definido (dentro do mundo PHP), use an =
para a condição WHERE; se não estiver, use >0
.
Posso limpar um pouco isso no PHP e fazer algo como:
$where = $variable ? 'column = ?' : column > ?'; // ternary operator to build the proper where condition
$sql = 'SELECT * FROM table WHERE $where';
$db->row($sql, [$variable ?? 0]); // bind parameters to the query, PDO way, and the operator will use the value of $variable if it is defined otherwise it will use 0
e vai funcionar bem, eu acho. Agora, gostaria de saber se posso conseguir o mesmo usando SQL simples como uma condição dentro de WHERE igual a SELECT e, em caso afirmativo, é ideal? Ou programaticamente é melhor e mais rápido?
Sim.
Não.
Sim.
Cada expressão em uma
WHERE
cláusula é chamada de predicado. Quanto mais complexa for a expressão, mais difícil será a otimização do mecanismo SQL. Eventualmente, pode prejudicar a sargabilidade do predicado. Sargabilidade é a qualidade da probabilidade de um predicado ser aplicável para uma operação eficiente de busca de índice. Um predicado que não seja sargável provavelmente resultará em uma operação de menor desempenho para servir os dados da consulta.Fazer a lógica mais complexa do lado do aplicativo para construir um predicado mais simples normalmente é melhor e mais eficiente, quando possível.
Conforme discutido nos comentários, este seria o pseudocódigo de como alguém poderia construir logicamente um predicado semelhante em SQL puro:
O
OR
operador é o que essencialmente prejudica a sargabilidade aqui. Poderíamos reescrever isso de forma mais eficiente em SQL puro usando umUNION
operador assim:À primeira vista, pode parecer contra-intuitivo consultar a mesma tabela duas vezes, mas o mecanismo normalmente é inteligente o suficiente para eliminar o que não se aplica. Por exemplo, neste caso, ou a variável tem um valor ou não, então apenas um lado do
UNION ALL
operador é processado.FWIW, este pseudocódigo é na verdade uma sintaxe T-SQL válida para o Microsoft SQL Server (caso você acabe trabalhando nesse sistema).