W3docs

MySQL Order By

Как сортировать результаты MySQL-запросов в Python с помощью ORDER BY: по возрастанию, убыванию, нескольким столбцам, с WHERE и LIMIT.

В этой главе показано, как сортировать результаты MySQL-запросов в Python с помощью предложения ORDER BY. Вы узнаете, как выполнять сортировку по возрастанию и убыванию, по нескольким столбцам, комбинировать ORDER BY с WHERE и LIMIT, а также применять лучшие практики Python: параметризованные запросы и корректную обработку ошибок.

Что делает ORDER BY

Предложение ORDER BY указывает MySQL возвращать строки в заданном порядке, а не в порядке хранения (который непредсказуем). Можно сортировать по одному или нескольким столбцам в порядке возрастания (ASC) или убывания (DESC).

SELECT column1, column2
FROM table_name
ORDER BY column1 ASC, column2 DESC;

Основные правила:

  • ASC (по возрастанию, A → Z, 0 → 9) — значение по умолчанию, его можно опустить.
  • DESC (по убыванию, Z → A, 9 → 0) нужно указывать явно.
  • Несколько столбцов разделяются запятыми; MySQL сначала сортирует по первому столбцу, а второй используется для разрешения совпадений.
  • Значения NULL при сортировке ASC идут перед не-NULL значениями, а при DESC — после них.

Требования

Вам понадобится пакет mysql-connector-python. Установите его один раз с помощью pip:

pip install mysql-connector-python

Во всех примерах ниже предполагается наличие таблицы customers с как минимум столбцами id, name и address. Если вам нужно создать её, обратитесь к разделу Python MySQL – Create Table.

Сортировка по возрастанию (по умолчанию)

Порядок по возрастанию используется по умолчанию, поэтому ASC необязателен. Следующий запрос возвращает всех клиентов, отсортированных по имени в алфавитном порядке:

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    mycursor.execute("SELECT * FROM customers ORDER BY name")

    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Database error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

Блок try / except / finally гарантирует закрытие соединения даже при возникновении ошибки.

Сортировка по убыванию

Добавьте DESC после имени столбца, чтобы изменить порядок сортировки на обратный. Этот запрос возвращает клиентов, отсортированных от Z до A:

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    mycursor.execute("SELECT * FROM customers ORDER BY name DESC")

    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Database error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

Сортировка по нескольким столбцам

Когда в первом столбце сортировки встречаются одинаковые значения, MySQL использует второй столбец для их разрешения. Это удобно, например, когда нужно отсортировать клиентов сначала по городу, а затем по имени в пределах каждого города:

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Sort by address (city) ascending, then by name ascending within each city
    mycursor.execute("SELECT * FROM customers ORDER BY address ASC, name ASC")

    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Database error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

Каждый столбец в многоколоночной сортировке может иметь собственное направление:

-- Most recent orders first; within the same date, highest total first
SELECT * FROM orders ORDER BY order_date DESC, total_amount DESC;

Комбинирование ORDER BY с WHERE

ORDER BY применяется после того, как WHERE отфильтровал строки. Используйте параметризованные запросы (заполнитель %s), чтобы безопасно передавать значения — никогда не вставляйте пользовательский ввод напрямую в SQL-строку.

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Find all customers in London, sorted by name
    sql = "SELECT * FROM customers WHERE address = %s ORDER BY name ASC"
    val = ("London",)
    mycursor.execute(sql, val)

    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Database error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

Заполнитель %s подставляется самим MySQL (а не форматированием строк Python), что предотвращает SQL-инъекции независимо от содержимого значения.

Комбинирование ORDER BY с LIMIT

Используйте LIMIT вместе с ORDER BY для реализации шаблонов вроде «топ N записей» или постраничного вывода. Порядок сортировки в SQL-запросе должен стоять перед LIMIT.

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # The 5 customers whose names come first alphabetically
    mycursor.execute("SELECT * FROM customers ORDER BY name ASC LIMIT 5")

    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Database error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

Для постраничного вывода (пропуска предыдущих страниц) добавьте OFFSET:

-- Page 2: rows 6–10
SELECT * FROM customers ORDER BY name ASC LIMIT 5 OFFSET 5;

Подробное описание LIMIT и OFFSET см. в разделе Python MySQL – Limit.

fetchone, fetchall и fetchmany

После выполнения запроса с ORDER BY результаты можно получить разными способами:

МетодВозвращаетКогда использовать
fetchall()Список всех подходящих кортежейРезультирующий набор достаточно мал, чтобы поместиться в памяти
fetchone()Первую строку в виде кортежа (или None)Нужна только верхняя запись
fetchmany(n)Список из следующих n строкОбработка большого результата по частям

Пример — получение только первого клиента в алфавитном порядке:

mycursor.execute("SELECT * FROM customers ORDER BY name ASC")
top = mycursor.fetchone()
print(top)  # e.g. (1, 'Alice', 'London')

Распространённые ошибки

Сортировка чисел, хранящихся как строки. Если в столбце числа хранятся как VARCHAR, MySQL сортирует их лексикографически ('10' идёт перед '9'). Приводите столбец к числовому типу, когда нужна числовая сортировка:

SELECT * FROM products ORDER BY CAST(price AS DECIMAL(10,2)) ASC;

Сортировка без ORDER BY недетерминирована. MySQL не гарантирует порядок строк без указания ORDER BY. Полагаться на порядок вставки ненадёжно — он непредсказуемо изменится по мере роста таблицы или изменения индексов.

Псевдонимы столбцов работают в ORDER BY. Если в SELECT задан псевдоним, его можно использовать в ORDER BY:

SELECT name, address AS city FROM customers ORDER BY city ASC;

Позиция в ORDER BY. Можно ссылаться на столбец по его позиции в списке SELECT (например, ORDER BY 1), но это хрупкое решение — избегайте его в рабочем коде, так как оно молча ломается при изменении порядка столбцов.

Связанные разделы

Was this page helpful?