2011-08-10 70 views
8

運行此查詢:PostgreSQL的混合排序的字母數字數據

select name from folders order by name 

返回這些結果:

alphanumeric 
a test 
test 20 
test 19 
test 1 
test 10 

但我預計:

a test 
alphanumeric 
test 1 
test 10 
test 19 
test 20 

有什麼不對嗎?

+1

它看起來很奇怪:''test 20'''test 19'。通過檢查'SHOW lc_collat​​e;'你有什麼'LC_COLLATE'?我有'en_US.UTF-8',它會以'ORDER BY name ASC'的形式返回所需的輸出。 –

+0

我也得到同樣的東西。我只是'選擇'字母數字''''測試'並得到'f'。 –

+1

爲記錄,我發佈了一個答案,指向你手動輸入整理。它被認爲不是huggy-足夠愛,所以我刪除它。但我認爲你應該從那裏開始。 –

回答

3

您可以手動排序的情況下,分割文本那裏的尾隨數字,像這樣:

SELECT * FROM sort_test 
ORDER BY SUBSTRING(text FROM '^(.*?)(\\d+)?$'), 
     COALESCE(SUBSTRING(text FROM ' (\\d+)$')::INTEGER, 0); 

這將排序列文,首先由所有字符可選地不結束空格,然後由數字,然後由這些可選數字。

在我的測試中工作得很好。

更新修復了簡單的coalesce(duh)的僅字符串排序。

+0

爲什麼downvote?它的工作,並解決了這種情況。這不是最好的解決方案,但它不涉及更改數據庫結構。至少如果你覺得需要downvote的話。 – OverZealous

+0

-1對於不能解決真正問題的怪異克魯格。 (關於具有多個空格和/或數字的字符串呢?)請參閱上面關於排序規則的註釋。 –

+0

我不會說這是一個*奇怪的kludge *。它增加了以數字方式對尾隨數字進行排序的功能,而不需要特定版本的PG。它非常好地處理*尾隨*號碼,所以適用於順序編號的文件夾。它處理多個空格,因爲它只檢查以確保在尾部數字之前至少有一個空格。如果你嘗試過,你會看到它的工作,而不是假設。 – OverZealous

16

你可以簡單地投namebytea數據類型,允許整理無關排序:

SELECT name 
FROM folders 
ORDER BY name::bytea; 

結果:

 name  
-------------- 
a test 
alphanumeric 
test 1 
test 10 
test 19 
test 20 
(6 rows) 
+1

主!這個答案絕對是我一直在尋找的最後2個小時!來自Mysql,在沒有編號的情況下將varchars轉換爲整數時不會產生錯誤.... – gabn88

+0

這修復了「TRIM」無法解決的前導空格的排序問題。 –

2

過分熱心的回答幫我,但沒有工作,如果在字符串數據庫以數字開頭,後跟其他字符。

以下爲我工作:

SELECT name 
FROM folders 
ORDER BY 
COALESCE(SUBSTRING(name FROM '^(\\d+)')::INTEGER, 99999999), 
SUBSTRING(name FROM '^\\d* *(.*?)(\\d+)?$'), 
COALESCE(SUBSTRING(name FROM ' (\\d+)$')::INTEGER, 0), 
name; 

所以這一個:

  1. 提取字符串中的第一個號碼,或者使用99999999
  2. 提取物下面的可能的第一串數。
  3. 提取尾隨號碼,或使用0
0

Tor的最後一個SQL爲我工作。但是,如果您從PHP調用此代碼,則需要添加額外的斜線。

SELECT name 
FROM folders 
ORDER BY 
COALESCE(SUBSTRING(name FROM '^(\\\\d+)')::INTEGER, 99999999), 
SUBSTRING(name FROM '^\\\\d* *(.*?)(\\\\d+)?$'), 
COALESCE(SUBSTRING(name FROM ' (\\\\d+)$')::INTEGER, 0), 
name; 
2

所有這些方法來分類我按字母順序排列的選擇:

test 1 
test 10 
test 2 
test 20 

該解決方案爲我(LC_COLLATE: 'ru_RU.UTF8'):

SELECT name 
FROM folders 
ORDER BY SUBSTRING(name FROM '([0-9]+)')::BIGINT ASC, name; 

test 1 
test 2 
test 10 
test 20 
0

一個VLK的回答上面幫了我很多,但是它只對數字部分進行了排序,在我的情況下排在第二位。我的數據就像(桌子1,桌子2,桌子3 ......)一個字符串部分,一個空格和一個數字部分。 A Vlk答案中的語法返回了按數字排序的數據,並且這是上述唯一的答案。然而,當琴絃部分不同時(例如桌子3,桌子4,桌子1,桌子5 ...)表1將從桌面2開始第一個。我使用以下語法對此進行了修復:

...order by SUBSTRING(name,'\\w+'), SUBSTRINGname FROM '([0-9]+)')::BIGINT ASC;