W3docs

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], ...;
  • ASC ordena de forma ascendente (A→Z, 0→9, mais antigo→mais novo) e é o padrãoORDER BY age e ORDER BY age ASC são idênticos.
  • DESC ordena 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:

nomepaísidade
AnnaCanada41
BenCanada29
CarlaMexico50

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 é NULL aparecem 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 BY nunca recebe valores do usuário, portanto não usa parâmetros vinculados. Quaisquer valores de WHERE na mesma consulta ainda devem ser vinculados com um prepared statement.

Armadilhas comuns

  • Ordenar por uma coluna de string com números (por exemplo, uma age armazenada como VARCHAR) ordena lexicamente: "10" vem antes de "9". Armazene números em uma coluna numérica ou faça o cast com ORDER BY CAST(age AS UNSIGNED).
  • ORDER BY com LIMIT é como você obtém os "N primeiros" resultados: ORDER BY age DESC LIMIT 5 retorna os cinco mais velhos. Sem ORDER BY, as linhas que o LIMIT manté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 BY permite 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.

Prática

Prática
Qual é o propósito da instrução ORDER BY no MySQL conforme descrito no site?
Qual é o propósito da instrução ORDER BY no MySQL conforme descrito no site?
Was this page helpful?