#sql #ms-access #sql-order-by
#sql #ms-access #sql-порядок по
Вопрос:
В SQL (с использованием Access) у меня есть следующие значения в столбце:
Одобрено, пункт 2, …, Пункт 10, Пункт 11, …, Пункт 21
Теперь, если я использовал порядок по column asc
, пункт 11 предшествует пункту 2. Я хочу, чтобы пункт 2, пункт 3 предшествовал пункту 11. Как это сделать?
Комментарии:
1. Это потому, что вы выполняете лексикографическую сортировку . То, что вы ищете, — это комбинированная лексикографическая и числовая сортировка. Вероятно, вам придется обрабатывать это вручную.
2. Вы все еще можете отсортировать его в предложении WHERE, но вам нужно разделить текстовый столбец на текст число, где вы дополняете число пробелами или нулями. Но вам нужно разработать схему разделения его таким образом, чтобы он обрабатывал значения, которые не соответствуют шаблону «<текст><число>».
3. Самым простым способом, если вы в состоянии изменить данные, было бы добавить начальный 0 к однозначным значениям, т.е. «Точка 2» станет «Точкой 02». Очевидно, что это может стать неуправляемым, если у вас много записей, хотя необходимость менять «Точку 2» на «Точку 0002», чтобы она появилась раньше «Точки 1000», может оказаться нежелательной.
4. У меня нет доступа к изменению данных, но ваша точка зрения верна. Спасибо!!!
5. @csl : как вы предлагаете использовать предложение WHERE для выполнения сортировки ay?
Ответ №1:
Если вы знаете, что это они всегда будут в форме «номер имени», что вы можете сделать, это добавить два столбца, которые разделяют этот исходный столбец, и отсортировать по ним вместо исходного
например,
SELECT foo2.foo,
Left(foo,InStr(foo," ")) AS foo_name,
CLng(IIf(InStr(foo," ")>0, Right(nz(foo,0),
Len(nz(foo,0))-InStr(nz(foo,0)," ")),"0")) AS foo_number
FROM foo2
ORDER BY Left(foo,InStr(foo," ")),
CLng(IIf(InStr(foo," ")>0, Right(nz(foo,0),
Len(nz(foo,0))-InStr(nz(foo,0)," ")),"0"));
(закодировано и протестировано)
Это должно дать вам такие результаты, как:
foo foo_name foo_number
--- -------- ----------
Approved Approved
Point 2 Point 2
Point 10 Point 10
Point 11 Point 11
Point 21 Point 21
и сортировка будет работать с частью foo_number.
Комментарии:
1. Чтобы заставить это работать в Access, вам нужно
Order By
left(foo,InStr(foo," ")), clng(right(foo, len(foo) - instr(foo," ")))
и, конечно же, выбратьfrom
что-нибудь! 😉2. @ CREsults: Спасибо. Он показывает несоответствие типов данных мне, когда я пытаюсь упорядочить по предложению «clng(right(Session, len(Session) — instr(Session,’ ‘)))»
3. @Conrad Frix — нет, но это лучше справилось бы с ситуацией «Точки 11 A».
4.
ORDER BY 2, 3
на мой взгляд, выглядит намного приятнее.5. Значение Val («11 A») дает 11. CLng («11 A») выдает ошибку несоответствия типов.
Ответ №2:
Я протестировал это, и кажется, что Access достаточно «умен», чтобы знать, чего вы хотите. Это минимум, который вам нужно сделать.
SELECT YourFields
FROM YourTable
ORDER BY
PointColumn,
Mid([PointColumn],6)
Этот подход и другие подобные ему не применимы, поэтому, если вы хотите фильтровать записи < Point 10
, это будет медленно.
Поэтому вместо этого я рекомендую вам нормализовать свои данные. Добавьте поле с именем IsApproved (boolean) и добавьте другое поле с именем point, которое отслеживает точки
Тогда легко делать такие вещи, как
SELECT IIF(IsApproved, "Approved", "Point " amp; [Point]) as output
FROM
table
WHERE
IsApproved = true or Point < 10
ORDER BY
IsApproved,
Point
Ответ №3:
Не уверен насчет access, но если есть функция replace, то вы могли бы сделать что-то вроде этого (например, в sql server):
select *, cast ( replace( replace( pointColumnName, 'Point', ''), 'Approved', 1000) as int ) as points
from tblName
order by points
где tblName — это таблица, а pointColumnName — столбец с вашими данными.
Комментарии:
1. Диалект Access SQL не включает
replace
-но Access позволяет вам включать (некоторые) функции VBA в ваши инструкции SQL (включая VBAReplace
).
Ответ №4:
Что касается производительности, то обычными трюками являются два:
-
Сортировка с использованием
varcharcol, intcol
(varcharcol, содержащий «Точку», и intcol, содержащий число) -
Добавьте дополнительный индексированный столбец, содержащий «Точку 000001», «Точку 000010», «Точку 000020» и т.д. с достаточным количеством нулей, чтобы вместить то, что вам нужно.
Ответ №5:
Для краткости..
SELECT * From MyTable
Order By Int(Replace(MyColumn,'Point',''))