簡體   English   中英

排序字母數字列

[英]Sort alphanumeric column

我在數據庫中有一列:

Serial Number
-------------
S1
S10
...
S2
S11
..
S13

我想對序列號<= 10進行如下排序並返回結果:

S1
S2
S10

我嘗試的一種方法是:

select Serial_number form table where Serial_Number IN ('S1', 'S2',... 'S10');

這解決了目的,但正在尋找更好的方法

這是此格式的一種簡便方法:

order by length(Serial_Number),
         Serial_Number

之所以可行,是因為前綴( 'S' )在所有值上的長度都是相同的。

對於Postgres,您可以使用以下代碼:

select serial_number
from the_table
order by regexp_replace(serial_number, '[^0-9]', '', 'g')::integer;

regexp_replace將刪除所有非數字字符,並且將結果視為適合“適當”排序的數字。

編輯1:

您可以使用新的“數字”來限制查詢結果:

select serial_number
from (
  select serial_number, 
         regexp_replace(serial_number, '[^0-9]', '', 'g')::integer as snum
  from the_table
) t 
where snum <= 10
order by snum;

編輯2

如果收到錯誤ERROR: invalid input syntax for integer: ""則顯然您在serial_number列中具有不遵循您在問題中發布的格式的值。 這意味着regexp_replace()會刪除字符串中的所有字符,因此像S這樣的字符串會導致這種情況。

為防止這種情況,您需要使用以下方法從結果中排除這些行:

where length(regexp_replace(serial_number, '[^0-9]', '', 'g')) > 0

在內部選擇。 或者,如果由於某種原因需要這些行,請在選擇列表中進行處理:

select serial_number
from (
  select serial_number, 
         case
            when length(regexp_replace(serial_number, '[^0-9]', '', 'g')) > 0 then regexp_replace(serial_number, '[^0-9]', '', 'g')::integer as snum
            else null -- or 0 whatever you need
         end as snum
  from the_table
) t 
where snum <= 10
order by snum;

這是一個很好的示例,說明了為什么永遠不要在一個列中混用兩種不同的東西。 如果所有序列號都帶有前綴S ,則不應存儲該序列號,並將實數放在實integer (或bigint )列中。

使用諸如NOT_SET類的NOT_SET來表示缺失值也是一個糟糕的選擇。 正是出於以下原因才發明了NULL值:表示沒有數據。

由於只有第一個字符會破壞您的數字樂趣,因此只需使用right()對其進行修剪並按數字值進行排序:

SELECT *
FROM   tbl
WHERE  right(serial_number, -1)::int < 11
ORDER  BY right(serial_number, -1)::int;

需要Postgres 9.1或更高版本。 在舊版本中,用substring (x, 10000)代替。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM