[英]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.