Как отсортировать столбец VARCHAR на сервере SQL, который содержит числа? - PullRequest
49 голосов
/ 23 сентября 2008

У меня есть столбец VARCHAR в базе данных SQL Server 2000, который может содержать буквы или цифры. Это зависит от того, как приложение настроено на клиентской стороне.

Когда он содержит числа, я хочу, чтобы он был отсортирован по номерам, например как «1», «2», «10» вместо «1», «10», «2». Поля, содержащие только буквы или буквы и цифры (например, «А1»), можно сортировать в алфавитном порядке, как обычно Например, это будет приемлемый порядок сортировки.

1
2
10
A
B
B1

Каков наилучший способ добиться этого?

Ответы [ 11 ]

70 голосов
/ 23 сентября 2008

Одним из возможных решений является заполнение числовых значений символом впереди, чтобы все они имели одинаковую длину строки.

Вот пример использования этого подхода:

select MyColumn
from MyTable
order by 
    case IsNumeric(MyColumn) 
        when 1 then Replicate('0', 100 - Len(MyColumn)) + MyColumn
        else MyColumn
    end

100 следует заменить фактической длиной этого столбца.

12 голосов
/ 23 сентября 2008

Есть несколько возможных способов сделать это.

Один будет

SELECT
 ...
ORDER BY
  CASE 
    WHEN ISNUMERIC(value) = 1 THEN CONVERT(INT, value) 
    ELSE 9999999 -- or something huge
  END,
  value

первая часть ORDER BY преобразует все в целое число (с огромным значением для нечисловых, чтобы сортировать в последнюю очередь), затем последняя часть заботится о алфавите.

Обратите внимание, что производительность этого запроса, вероятно, по меньшей мере умеренно страшна для больших объемов данных.

5 голосов
/ 13 января 2011
SELECT *, CONVERT(int, your_column) AS your_column_int
FROM your_table
ORDER BY your_column_int

OR

SELECT *, CAST(your_column AS int) AS your_column_int
FROM your_table
ORDER BY your_column_int

Думаю, оба довольно портативны.

5 голосов
/ 23 сентября 2008
select
  Field1, Field2...
from
  Table1
order by
  isnumeric(Field1) desc,
  case when isnumeric(Field1) = 1 then cast(Field1 as int) else null end,
  Field1

Это вернет значения в порядке, который вы задали в своем вопросе.

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

4 голосов
/ 03 апреля 2013

вы всегда можете конвертировать ваш varchar-столбец в bigint, так как целое число может быть слишком коротким ...

select cast([yourvarchar] as BIGINT)

но вы всегда должны заботиться об альфа-символах

where ISNUMERIC([yourvarchar] +'e0') = 1

+ 'e0' происходит от http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/isnumeric-isint-isnumber

это приведет к вашему заявлению

SELECT
  *
FROM
  Table
ORDER BY
   ISNUMERIC([yourvarchar] +'e0') DESC
 , LEN([yourvarchar]) ASC

первый столбец сортировки поместит число сверху. вторая сортировка по длине, поэтому 10 будет предшествовать 0001 (что глупо?!)

это приводит ко второй версии:

SELECT
      *
    FROM
      Table
    ORDER BY
       ISNUMERIC([yourvarchar] +'e0') DESC
     , RIGHT('00000000000000000000'+[yourvarchar], 20) ASC

второй столбец теперь дополняется справа '0', поэтому естественная сортировка помещает целые числа с ведущими нулями (0,01,10,0100 ...) в правильном порядке (правильно!) - но все альфы будут улучшены с '0'-символы (производительность)

третья версия:

 SELECT
          *
        FROM
          Table
        ORDER BY
           ISNUMERIC([yourvarchar] +'e0') DESC
         , CASE WHEN ISNUMERIC([yourvarchar] +'e0') = 1
                THEN RIGHT('00000000000000000000' + [yourvarchar], 20) ASC
                ELSE LTRIM(RTRIM([yourvarchar]))
           END ASC

теперь числа сначала дополняются символами '0' (конечно, длина 20 может быть увеличена) - что сортирует числа вправо - и альфы только обрезаются

4 голосов
/ 21 июля 2011

Я решил это очень просто, написав это в части «заказ»

ORDER BY (
sr.codice +0
)
ASC

Кажется, это работает очень хорошо, на самом деле у меня была следующая сортировка:

16079   Customer X 
016082  Customer Y
16413   Customer Z

Таким образом, 0 перед 16082 считается правильным.

2 голосов
/ 23 сентября 2008

Это похоже на работу:

select your_column  
from your_table  
order by   
case when isnumeric(your_column) = 1 then your_column else 999999999 end,  
your_column   
0 голосов
/ 28 мая 2018

Это может помочь вам, я попробовал это, когда у меня возникла та же проблема.

SELECT * FROM tab ORDER BY IIF(TRY_CAST(val AS INT) IS NULL, 1, 0),TRY_CAST(val AS INT);

0 голосов
/ 22 мая 2017

Этот запрос полезен для вас. В этом запросе столбец имеет тип данных varchar, упорядоченный в хорошем порядке. Например, в этом столбце данные: - G1, G34, G10, G3. Итак, после выполнения этого запроса вы увидите результаты: - G1, G10, G3, G34.

SELECT *,
       (CASE WHEN ISNUMERIC(column_name) = 1 THEN 0 ELSE 1 END) IsNum
FROM table_name 
ORDER BY IsNum, LEN(column_name), column_name;
0 голосов
/ 10 мая 2016
 SELECT *,
       ROW_NUMBER()OVER(ORDER BY CASE WHEN ISNUMERIC (ID)=1 THEN CONVERT(NUMERIC(20,2),SUBSTRING(Id, PATINDEX('%[0-9]%', Id), LEN(Id)))END DESC)Rn ---- numerical
        FROM
            (

        SELECT '1'Id UNION ALL
        SELECT '25.20' Id UNION ALL

    SELECT 'A115' Id UNION ALL
    SELECT '2541' Id UNION ALL
    SELECT '571.50' Id UNION ALL
    SELECT '67' Id UNION ALL
    SELECT 'B48' Id UNION ALL
    SELECT '500' Id UNION ALL
    SELECT '147.54' Id UNION ALL
    SELECT 'A-100' Id
    )A

    ORDER BY 
    CASE WHEN ISNUMERIC (ID)=0                                /* alphabetical sort */ 
         THEN CASE WHEN PATINDEX('%[0-9]%', Id)=0
                   THEN LEFT(Id,PATINDEX('%[0-9]%',Id))
                   ELSE LEFT(Id,PATINDEX('%[0-9]%',Id)-1)
              END
    END DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...