У меня есть столбец с именем 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();
Laravel правильно следует вашим инструкциям, так как вы хотите отсортировать текст на основе его логики посимвольного сравнения по умолчанию. Поэтому результат хоть и не тот, что вы задумали, но все же правильный!
Если вы хотите установить собственный порядок сортировки, на мой взгляд, лучшим решением будет разделить столбец на три части. (Предполагается, что синтаксис: текст - числовой текст.)
// Example
/*
N... - 1 O...
N... - 11 O...
A... - 11 O...
N... - 2 S...
N... - 11 A...
*/
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"
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
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"?
Как использовать функции SQL в вашем запросе Laravel?
я включил новый снимок экрана с надписью измененный снимок экрана, вот как он выглядит после вашего кода.
Я редко использую эту функцию, возможно, она получила слишком мало информации от функции RAW, и направление сортировки нужно добавить в конец: ASC. Я обновил свой ответ.
О, я был неосторожен. Мы пишем код SQL, поэтому нам не нужны апострофы вокруг имени столбца... Я их удалил. Теперь точно должно работать ;)
Как вы уже поняли, вы не можете сортировать числа так же, как сортируете текст. 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
Не имею представления. Вы не предоставили код или контекст для своего вопроса. Все, что мы знаем, это то, что у вас есть список значений, которые вы хотите отсортировать. Поскольку вопрос был помечен laravel, я предположил, что вы можете преобразовать список в коллекцию.
Это может быть так же просто, как использовать $a->case_id
и $b->case_id
в вызовах preg_match()
вместо просто $a
и $b
, но я не знаю.
Текущее состояние вопроса сильно отличается от исходного. Пожалуйста, попробуйте указать свои требования для следующих вопросов