Entendendo a Cláusula MySQL ORDER BY em PHP
Aprenda a usar a cláusula ORDER BY do MySQL em PHP para ordenar resultados de consultas de forma segura, incluindo múltiplas colunas e valores NULL.
Uma consulta SELECT sem ORDER BY retorna linhas em uma ordem que o MySQL não garante — ela pode mudar entre execuções, versões do servidor ou após manutenção de tabelas. A cláusula ORDER BY torna essa ordem explícita, classificando o conjunto de resultados por uma ou mais colunas. Esta página mostra como usá-la a partir do PHP: a sintaxe, ascendente vs descendente, ordenação por várias colunas, onde os valores NULL ficam e como ordenar por uma coluna fornecida pelo usuário com segurança para não abrir uma brecha de SQL injection.
Se você é novo na execução de consultas a partir do PHP, comece com conectar ao MySQL e selecionar dados primeiro.
Sintaxe
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;ASCordena de forma ascendente (A→Z, 0→9, mais antigo→mais novo) e é o padrão —ORDER BY ageeORDER BY age ASCsão idênticos.DESCordena de forma descendente (Z→A, 9→0, mais novo→mais antigo).- A direção se aplica por coluna, então você pode misturá-las:
ORDER BY country ASC, age DESC.
ORDER BY é executado após a filtragem por WHERE e GROUP BY, portanto ordena apenas as linhas que sobreviveram a essas etapas. É a última cláusula antes de LIMIT.
Um exemplo básico
Isso seleciona nomes e idades e ordena os clientes mais velhos primeiro:
<?php
$conn = new mysqli("localhost", "username", "password", "database");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT name, age FROM customers ORDER BY age DESC";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "Name: " . $row["name"] . " - Age: " . $row["age"] . "<br>";
}
} else {
echo "0 results";
}
$conn->close();
?>Nos conectamos com a classe mysqli, selecionamos name e age de customers, e usamos ORDER BY age DESC para que a maior idade venha primeiro. Troque DESC por ASC (ou remova) para colocar os mais jovens primeiro.
Ordenando por múltiplas colunas
Quando várias linhas compartilham o mesmo valor na primeira coluna de ordenação, a próxima coluna desempata. A ordem das colunas na cláusula é a ordem de precedência:
SELECT name, country, age
FROM customers
ORDER BY country ASC, age DESC;Isso agrupa os clientes por country em ordem alfabética e, dentro de cada país, lista os mais velhos primeiro. Com os dados abaixo:
| nome | país | idade |
|---|---|---|
| Anna | Canada | 41 |
| Ben | Canada | 29 |
| Carla | Mexico | 50 |
ORDER BY country ASC, age DESC retorna Anna, Ben, Carla — Canada antes de Mexico, e Anna antes de Ben porque 41 > 29.
Como os valores NULL são ordenados
No MySQL, NULL é tratado como menor do que qualquer valor não-NULL:
- Com
ASC, as linhas onde a coluna de ordenação éNULLaparecem primeiro. - Com
DESC, elas aparecem por último.
Para forçar os NULLs ao final independentemente da direção, ordene primeiro pelo fato de a coluna ser nula:
SELECT name, last_login
FROM users
ORDER BY last_login IS NULL, last_login DESC;last_login IS NULL avalia para 0 em datas reais e 1 para nulos, então as linhas não nulas (0) vêm antes das nulas (1).
Ordenando por uma coluna escolhida em tempo de execução (com segurança)
Uma necessidade comum é permitir que o usuário escolha a coluna de ordenação — por exemplo ?sort=name. Você não pode vincular um nome de coluna ou a palavra-chave ASC/DESC com um placeholder de prepared statement; os placeholders funcionam apenas para valores. Concatenar a requisição bruta no SQL seria uma vulnerabilidade de SQL injection. Em vez disso, valide a entrada contra uma lista de permissões:
<?php
// Map user input to known-good column names.
$allowedColumns = [
"name" => "name",
"age" => "age",
"date" => "created_at",
];
$sortKey = $_GET["sort"] ?? "name";
$column = $allowedColumns[$sortKey] ?? "name"; // fallback if unknown
$direction = (($_GET["dir"] ?? "asc") === "desc") ? "DESC" : "ASC";
// $column and $direction can now only be values we put in the code.
$sql = "SELECT name, age FROM customers ORDER BY $column $direction";
$result = $conn->query($sql);
?>O usuário só fornece uma chave do array; o nome real da coluna e a direção vêm de constantes no seu código, então entradas não confiáveis nunca chegam à string da consulta. Este é o único lugar onde construir SQL por concatenação é aceitável — porque cada valor possível é um que você escreveu.
Nota: o próprio
ORDER BYnunca recebe valores do usuário, portanto não usa parâmetros vinculados. Quaisquer valores deWHEREna mesma consulta ainda devem ser vinculados com um prepared statement.
Armadilhas comuns
- Ordenar por uma coluna de string com números (por exemplo, uma
agearmazenada comoVARCHAR) ordena lexicamente:"10"vem antes de"9". Armazene números em uma coluna numérica ou faça o cast comORDER BY CAST(age AS UNSIGNED). ORDER BYcomLIMITé como você obtém os "N primeiros" resultados:ORDER BY age DESC LIMIT 5retorna os cinco mais velhos. SemORDER BY, as linhas que oLIMITmantém são imprevisíveis. Veja limitando dados.- Ordenar um conjunto de resultados grande pode ser lento se nenhum índice cobrir a coluna de ordenação; um índice na coluna do
ORDER BYpermite que o MySQL pule a etapa de ordenação.
Conclusão
ORDER BY transforma uma ordem de linhas indefinida em uma definida. Lembre-se do essencial: ASC é o padrão, as colunas são aplicadas da esquerda para a direita para desempate, NULL ordena em posição baixa e uma coluna de ordenação escolhida pelo usuário deve ser validada contra uma lista de permissões em vez de concatenada cegamente. Combinado com WHERE para filtragem e LIMIT para paginação, ele oferece controle total sobre quais linhas você retorna e em qual ordem.