Laravel orderBy игнорирует числовые значения в данных заказа

У меня есть столбец с именем Class ID, и я пытаюсь отсортировать этот столбец. Кажется, что игнорируются цифры. Я предполагаю, потому что это строки.

В настоящее время это выглядит так:

NewSyn - 1 OBSSt
NewSyn - 1 OBSSt
NewSyn - 1 OBSSt
NewSyn - 11 SH-B
NewSyn - 11 SH-B
NewSyn - 15 SH-O
NewSyn - 16 SH-On
NewSyn - 18 SH-S
NewSyn - 18 SH-S
NewSyn - 18 SH-S
NewSyn - 19 SHS
NewSyn - 19 SHS
NewSyn - 2 OBSB
NewSyn - 2 OBSB
NewSyn - 2 OBSB
NewSyn - 2 OBSB

Он должен быть отсортирован по алфавиту и с использованием числа так:

NewSyn - 1 OBSSt
NewSyn - 1 OBSSt
NewSyn - 1 OBSSt
NewSyn - 2 OBSB
NewSyn - 2 OBSB
NewSyn - 2 OBSB
NewSyn - 2 OBSB
NewSyn - 11 SH-B
NewSyn - 11 SH-B
NewSyn - 15 SH-O
NewSyn - 16 SH-On
NewSyn - 18 SH-S
NewSyn - 18 SH-S
NewSyn - 18 SH-S
NewSyn - 19 SHS
NewSyn - 19 SHS

Я пытался:

->orderBy('case_id', 'ASC')

Мой запрос

$cases = Classrooms::where('created_date', '>=' , $today)
    ->orderBy('case_id', 'ASC')
    ->get();

Текущее состояние вопроса сильно отличается от исходного. Пожалуйста, попробуйте указать свои требования для следующих вопросов

lezhni 31.05.2023 21:10
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
1
67
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Laravel правильно следует вашим инструкциям, так как вы хотите отсортировать текст на основе его логики посимвольного сравнения по умолчанию. Поэтому результат хоть и не тот, что вы задумали, но все же правильный!

Если вы хотите установить собственный порядок сортировки, на мой взгляд, лучшим решением будет разделить столбец на три части. (Предполагается, что синтаксис: текст - числовой текст.)


// Example
/*
N... - 1 O...
N... - 11 O...
A... - 11 O...
N... - 2 S...
N... - 11 A...
*/
1.) Заказ по тексту перед номером
orderByRaw("SUBSTRING_INDEX(your_column_name, ' ', 1) ASC")

// Result from Example
/*
A... - 11 O... // changed (move to here)
N... - 1 O...
N... - 11 O...
               // changed (moved from here)
N... - 2 S...
N... - 11 A...
*/
SELECT SUBSTRING_INDEX('NewSyn - 2 SH-On', ' ', 1);

# Result: "NewSyn"
2.) Заказ по номеру
orderByRaw("CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(your_column_name, ' ', -1), ' ', 1) AS UNSIGNED) ASC")

// Result from 1st orderBy
/*
A... - 11 O...
N... - 1 O...
N... - 2 S... // changed
N... - 11 O... // changed
N... - 11 A...
*/
SELECT CAST(SUBSTRING_INDEX(SUBSTRING_INDEX('NewSyn - 2 SH-On', ' - ', -1), ' ', 1) AS UNSIGNED);

# Result: 2
3.) Заказ по тексту после номера
orderByRaw("SUBSTRING_INDEX(your_column_name, ' ', -1) ASC")

// Result from 2nd orderBy
/*
A... - 11 O...
N... - 1 O...
N... - 2 S...
N... - 11 A... // changed
N... - 11 O... // changed
*/
SELECT SUBSTRING_INDEX('NewSyn - 2 SH-On', ' ', -1);

# Result: "SH-On"

Краткое содержание

YourModel::orderByRaw("SUBSTRING_INDEX(case_id, ' ', 1) ASC")
     ->orderByRaw("CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(case_id, ' ', -1), ' ', 1) AS UNSIGNED) ASC")
     ->orderByRaw("SUBSTRING_INDEX(case_id, ' ', -1) ASC")
     ->get();

Laravel выполняет сортировку в том порядке, в котором вы запрашиваете, поэтому, если вам нужно обратить внимание только на число и текст после него, вы можете выполнить задачу, используя 2-й и 3-й фрагменты кода (пропустив 1-й). Это зависит от требований вашего проекта и того, что вам нужно.

Ключевым моментом является то, что у нас есть возможность манипулировать сложными столбцами с помощью кода SQL. Мы можем передавать манипуляции со столбцами с помощью кода SQL в функции, известные как функции «RAW», такие как selectRaw, whereRaw, orderByRaw и т. д.

Крайне важно безопасно обрабатывать пользовательский ввод, чтобы предотвратить прямую передачу кода SQL. Вот почему для этого существует отдельный подход. Простой выбор, где, orderBy и другие функции никак не будут принимать код SQL, но функции RAW будут. В своем решении я использовал 3 последовательные RAW-функции, разделив текст на 3 части, что позволило мне сортировать каждую часть отдельно, как если бы они были из 3 разных столбцов.

Что такое функция "SUBSTRING_INDEX"?

Что такое функция "CAST"?

Как использовать функции SQL в вашем запросе Laravel?

я включил новый снимок экрана с надписью измененный снимок экрана, вот как он выглядит после вашего кода.

karen 31.05.2023 18:46

Я редко использую эту функцию, возможно, она получила слишком мало информации от функции RAW, и направление сортировки нужно добавить в конец: ASC. Я обновил свой ответ.

rozsazoltan 31.05.2023 19:04

О, я был неосторожен. Мы пишем код SQL, поэтому нам не нужны апострофы вокруг имени столбца... Я их удалил. Теперь точно должно работать ;)

rozsazoltan 31.05.2023 19:12

Как вы уже поняли, вы не можете сортировать числа так же, как сортируете текст. 2 всегда будет стоять после 1 в лексической сортировке, даже если эта 1 является частью 104.

Так что просто get()Collection экземпляр и передайте sortBy() функцию, которая будет делать то, что вы хотите. Здесь используется регулярное выражение для разделения чисел и текста, а затем используется оператор космического корабля для сравнения значений.

$result = collect([
    "NewSyn - 1 OBSSt", "NewSyn - 1 OBSSt", "NewSyn - 1 OBSSt", "NewSyn - 11 SH-B",
    "NewSyn - 11 SH-B", "NewSyn - 15 SH-O", "NewSyn - 16 SH-On", "NewSyn - 18 SH-S",
    "NewSyn - 18 SH-S", "NewSyn - 18 SH-S", "NewSyn - 19 SHS", "NewSyn - 19 SHS", 
    "NewSyn - 2 OBSB", "NewSyn - 2 OBSB", "NewSyn - 2 OBSB", "NewSyn - 2 OBSB",
]);

$sorted = $result->sortBy([function ($a, $b) {
    // number will be in first match, text in second
    $pattern = "/NewSyn - ([0-9]+) (.*)/";
    if (preg_match($pattern, $a, $a_matches) && preg_match($pattern, $b, $b_matches)) {
        // if numbers are the same (comparison returns 0) sort by text instead
        return $a_matches[1] <=> $b_matches[1] ?: $a_matches[2] <=> $b_matches[2];
    }
    return $a <=> $b;
}]);
dump($sorted->values()->toArray());

Вы не сказали, будут ли все пары число/текст одинаковыми, поэтому в этом примере будет выполнено сравнение текста, когда числа совпадают. Также предполагается, что значения также начинаются с «NewSyn-».

Выход:

array:16 [
  0 => "NewSyn - 1 OBSSt"
  1 => "NewSyn - 1 OBSSt"
  2 => "NewSyn - 1 OBSSt"
  3 => "NewSyn - 2 OBSB"
  4 => "NewSyn - 2 OBSB"
  5 => "NewSyn - 2 OBSB"
  6 => "NewSyn - 2 OBSB"
  7 => "NewSyn - 11 SH-B"
  8 => "NewSyn - 11 SH-B"
  9 => "NewSyn - 15 SH-O"
  10 => "NewSyn - 16 SH-On"
  11 => "NewSyn - 18 SH-S"
  12 => "NewSyn - 18 SH-S"
  13 => "NewSyn - 18 SH-S"
  14 => "NewSyn - 19 SHS"
  15 => "NewSyn - 19 SHS"
]

как бы я реализовал это в моем запросе, например, имя таблицы - классы и включает еще 3 столбца, идентификатор, учитель, помощник. Я только хочу отсортировать case_id

karen 31.05.2023 20:11

Не имею представления. Вы не предоставили код или контекст для своего вопроса. Все, что мы знаем, это то, что у вас есть список значений, которые вы хотите отсортировать. Поскольку вопрос был помечен laravel, я предположил, что вы можете преобразовать список в коллекцию.

miken32 31.05.2023 20:12

Это может быть так же просто, как использовать $a->case_id и $b->case_id в вызовах preg_match() вместо просто $a и $b, но я не знаю.

miken32 31.05.2023 20:19

Другие вопросы по теме