2013-07-06 40 views
0

我想開發一個系統來顯示網頁上的數據庫產品。通常情況下,這是沒有問題的,除了一個製造商有幾個不正常的零件編號,我需要正確排序。複雜的ORDER BY需要排序不規則的值

通常情況下,我可以使用一個無形的列來排序,但是這會使得在兩個較舊的項目之間插入新項目變得更加困難。

例如,這裏有一些零件號碼的:

1211 
1225 
14-302 
14-303 
2015 
23157 
3507 
35280UP 
42-3309 
42-3312 
4241 

現在,MFGR正常順序產生上述順序。 它應該是更多的東西是這樣的:

14-302 
14-303 
42-3309 
42-3312 
1211 
1225 
2015 
3507 
4241 
23157 
35280UP 

什麼將是上正確排序這是我最好的選擇?如果他們只是在csv文件中製作,然後上傳,這不會是一個問題。但由於數據庫自動更改,服務器將實時修改值。所以手動更新它是不可能的。這意味着後端將需要插入新項目,但通過什麼方法可以在另一個項目之間插入項目?我寧願不要求諸如小數之類的東西給我X之間的值(就像我有1.00和2.00,我想在他們之間放一個,所以我把它做成1.50)。

任何幫助,將不勝感激。

編輯:

我想對它進行排序的方法是這樣的: 如果有一個連字符,即14-302,它是由14個分類,然後任何14-XXX排序由連字符後面的數字表示。 然後,只有數字將按其實際的數量排序,802在45768之前。 然後,任何在它後面有一個字母的數字將按數字排序,123a這個字母在123b之前,但是在122之後。 123b在124c之前。 最後,任何以M開頭的東西都會被最後排序,並被連字符後面的數字排序。

+0

第1步:定義決定的排序規則。 –

+0

我以爲我有種病,但在編輯方面做得不錯。 – sharf

+0

這似乎是你可以使用mysql REGEXP的情況。以下是您的初創公司:http://sqlfiddle.com/#!2/ffd2ce/7您可以在此處瞭解更多有關此用法的信息:http://dev.mysql.com/doc/refman/5.6/en/regexp .html – Gimmy

回答

1

隨着您調整的問題,原則仍然是一樣的。 我的第一個直覺是與額外的領域,但你可以使用存儲的功能。 你仍然需要將你的零件編號分成3部分(我認爲它不超過)。

  • Part1是一個INTEGER,如果現有的第一個數字是其他數字,用maxint(part1最大)填充它。
  • Part2是一個CHAR,包含字母(如果存在)。
  • Part3是一個INTEGER,包含第二個數字(如果存在)。

您可以通過調用這些值的函數進行排序。

這裏是完整的資料來源: 爲了您的方便起見,請鏈接到工作SQL Fiddle。 這真的是草率/快速編程,但它的工作原理。在很短的時間內放在一起,我相信有改進的地方。你可以自己調整它。稍後,您可以從視圖中刪除part1,part2和part3。 (但把它留在order by)它只是顯示如何完成排序。

DROP PROCEDURE IF EXISTS `uGetParts`// 
DROP FUNCTION IF EXISTS `uExtractPart1`// 
DROP FUNCTION IF EXISTS `uExtractPart2`// 
DROP FUNCTION IF EXISTS `uExtractPart3`// 

CREATE PROCEDURE `uGetParts`(
    IN ins varchar(50), 
    OUT num1 int unsigned, 
    OUT num2 int unsigned, 
    OUT num3 int unsigned) 
NO SQL 
BEGIN 
    SET num1=0; 
    SET num2=0; 
    SET num3=0; 
    WHILE (num1<length(ins)) AND 
    (SUBSTRING(ins,num1+1,1) REGEXP('(^[0-9]+$)')=1) DO 
     SET num1=num1+1; 
    END WHILE; 
    SET num2=num1; 
    WHILE (num2<length(ins)) AND 
    (SUBSTRING(ins,num2+1,1) REGEXP('(^[0-9]+$)')=0) DO 
     SET num2=num2+1; 
    END WHILE; 
    SET num3=num2; 
    WHILE (num3<length(ins)) AND 
    (SUBSTRING(ins,num3+1,1) REGEXP('(^[0-9]+$)')=1) DO 
     SET num3=num3+1; 
    END WHILE; 
END// 

CREATE FUNCTION `uExtractPart1`(ins varchar(50)) 
RETURNS int unsigned NO SQL 
BEGIN 
    DECLARE num1 INT default 0; 
    DECLARE num2 INT default 0; 
    DECLARE num3 INT default 0; 
    call uGetParts(ins,num1,num2,num3); 
    IF num1>0 THEN  
    RETURN CAST(SUBSTRING(ins,1,num1) AS UNSIGNED); 
    ELSE 
    RETURN ~0 >> 32; 
    END IF; 
END// 

CREATE FUNCTION `uExtractPart2`(ins varchar(50)) 
RETURNS varchar(50) NO SQL 
BEGIN 
    DECLARE num1 INT default 0; 
    DECLARE num2 INT default 0; 
    DECLARE num3 INT default 0; 
    call uGetParts(ins,num1,num2,num3); 
    IF num2>num1 THEN  
    RETURN SUBSTRING(ins,num1+1,num2-num1); 
    ELSE 
    RETURN ''; 
    END IF; 
END//  

CREATE FUNCTION `uExtractPart3`(ins varchar(50)) 
RETURNS int unsigned NO SQL 
BEGIN 
    DECLARE num1 INT default 0; 
    DECLARE num2 INT default 0; 
    DECLARE num3 INT default 0; 
    call uGetParts(ins,num1,num2,num3); 
    IF num3>num2 THEN  
    RETURN CAST(SUBSTRING(ins,num2+1,num3-num2) AS UNSIGNED); 
    ELSE 
    RETURN 0; 
    END IF; 
END// 

你可以這樣調用:

SELECT 
    id, 
    TYPE, 
    uExtractPart1(TYPE) as part1, 
    uExtractPart2(TYPE) as part2, 
    uExtractPart3(TYPE) as part3 
FROM Article 
ORDER BY 
    uExtractPart1(TYPE), 
    uExtractPart2(TYPE), 
    uExtractPart3(TYPE) 
+0

把這個數字分成3個字段是可能的,但會很煩人。爲什麼我不能使用REGEXP? – sharf

+0

這取決於。你說它在你的設置中沒有「正常工作」。你是什​​麼意思? (排序與您在原始問題中陳述的完全一樣) – Rik

+0

排序並不把它放在我原來的問題中。整理出1211,3507,23157,2015,1225等,這是不對的。它應該是1211年,1225年,2015年,3507年,23157年。 – sharf