我有一個包含軟件發行版本的數據庫,我希望能夠撤回所有版本大於當前版本的版本號。但是,這些版本以自定義(但標準)方式進行排序 - 從alpha版本到beta版本,再到主要版本到補丁。因此,這裏的排序的例子:SQL大於自定義排序
100a1
100a4
100b1
100
100p1
101
101p3
etc.
是否有可能形成拉回給出的自定義排序此數據或不會>只爲給定的排序像整數和日期工作的SQL查詢?如果這有什麼區別,我正在與MSSQL合作。
我有一個包含軟件發行版本的數據庫,我希望能夠撤回所有版本大於當前版本的版本號。但是,這些版本以自定義(但標準)方式進行排序 - 從alpha版本到beta版本,再到主要版本到補丁。因此,這裏的排序的例子:SQL大於自定義排序
100a1
100a4
100b1
100
100p1
101
101p3
etc.
是否有可能形成拉回給出的自定義排序此數據或不會>只爲給定的排序像整數和日期工作的SQL查詢?如果這有什麼區別,我正在與MSSQL合作。
這是我的代碼示例。不是最短的一個,但它擁有許多演示輸入/輸出,如果你明白我想要什麼,可以進一步簡化。
CREATE TABLE #versions(version nvarchar(10))
INSERT INTO #versions(version)
VALUES(N'100a1'),(N'100a4'),(N'100b1'),(N'100p1'),(N'100'),(N'101'),(N'101p3')
-- Just an example using substrings etc. how to get the
SELECT version,
SUBSTRING(version,1,
CASE
WHEN PATINDEX(N'%[a-z]%',version) > 0
THEN PATINDEX(N'%[a-z]%',version)-1
ELSE LEN(version)
END
) as version_number,
SUBSTRING(version,
CASE
WHEN PATINDEX(N'%[a-z]%',version) > 0
THEN PATINDEX(N'%[a-z]%',version)
ELSE 0
END, PATINDEX(N'%[0-9]%',
SUBSTRING(version,1,
CASE
WHEN PATINDEX(N'%[a-z]%',version) > 0
THEN PATINDEX(N'%[a-z]%',version)-1
ELSE LEN(version)
END
)
)
) as version_suffix,
SUBSTRING(version,
PATINDEX(N'%[a-z]%',
SUBSTRING(version,
CASE
WHEN PATINDEX(N'%[a-z]%',version) > 0
THEN PATINDEX(N'%[a-z]%',version)
ELSE LEN(version)
END, LEN(version)
)
),
PATINDEX(N'%[0-9]%',
SUBSTRING(version,1,
CASE
WHEN PATINDEX(N'%[a-z]%',version) > 0
THEN PATINDEX(N'%[a-z]%',version)-1
ELSE LEN(version)
END
)
)
) as version_sub
FROM #versions
-- Now your code:
;WITH vNumber AS(
SELECT version,SUBSTRING(version,1,
CASE
WHEN PATINDEX(N'%[a-z]%',version) > 0
THEN PATINDEX(N'%[a-z]%',version)-1
ELSE LEN(version)
END
) as version_number
FROM #versions
), vSuffix AS(
SELECT version, SUBSTRING(version,
CASE
WHEN PATINDEX(N'%[a-z]%',version) > 0
THEN PATINDEX(N'%[a-z]%',version)
ELSE LEN(version)
END, LEN(version)
) as version_suffix
FROM #versions
)
SELECT dat.version
FROM (
SELECT vn.version, vn.version_number,
CASE
SUBSTRING(vn.version,
CASE
WHEN PATINDEX(N'%[a-z]%',vn.version) > 0
THEN PATINDEX(N'%[a-z]%',vn.version)
ELSE 0
END, 1
)
WHEN N'a' THEN 1
WHEN N'b' THEN 2
WHEN N'' THEN 3
WHEN N'p' THEN 4
END as version_suffix,
SUBSTRING(vn.version,
PATINDEX(N'%[a-z]%',
vs.version_suffix
),
PATINDEX(N'%[0-9]%',
SUBSTRING(vn.version,1,
CASE
WHEN PATINDEX(N'%[a-z]%',vn.version) > 0
THEN PATINDEX(N'%[a-z]%',vn.version)-1
ELSE LEN(vn.version)
END
)
)
) as version_sub
FROM vNumber as vn
INNER JOIN vSuffix as vs
ON vn.version = vs.version
) AS dat
ORDER BY dat.version_number, dat.version_suffix, dat.version_sub
DROP TABLE #versions
這是我輸入:
version
----------
100a1
100a4
100b1
100p1
100
101
101p3
這是結果:
version
----------
100a1
100a4
100b1
100
100p1
101
101p3
反正。我建議將這些值分成不同的列。它會讓你的生活更輕鬆。 :-)
只要你能真正描述排序應該如何工作,當然可以。
的兩種基本方法是:
order by left([Version] + '__', 5)
的東西。從更復雜的值中取出一個整數也是可行的。order by
中的所有值。這是在SQL中處理這個問題的更習慣的方式 - 基本上,當你在邏輯上使用101, p, 1
時,爲什麼使用一個值101p1
?解析在SQL中處理有點棘手,因爲SQL確實是爲規範化數據集設計的 - 而且您可以將多個值有效地存儲在一列中。如果你的規則不是太複雜,但這應該仍然可行。但它不會很漂亮:D
對於固定長度的值,這當然很簡單 - 這相當於使用了例如001p01
作爲文件系統中的文件名 - 按字母排序是正確的排序順序。然後你可以簡單地使用整個值的order by
,或者根據substring
s將它分成幾部分。對於具有分隔符的值,它有點醜陋,但仍然非常容易 - 1.p.1
可以相對容易地分割,然後您可以按順序依次對每個部分進行排序。
但是,您的系統似乎比機器更適合人類 - 沒有真正的提示可以遵循。基本上,你似乎在看「數字,字母,數字......把數字看作數字,把字母看作字母」。在T-SQL中處理這實際上非常棘手。不過,可能值得引入CLR的幫助,尤其是正則表達式 - 不過我不確定您是否能夠爲無限數量的數字/字母組處理這個問題。
迄今爲止最簡單的方法似乎是將版本列簡單地分成多列,每列只有一個值 - 類似於MajorVersion, Level, Revision
或類似的東西,對應於101, Alpha, 3
。
我在下面的代碼示例中採用了第二種方法。但主要是我會建議有這個單獨的列:) – Ionic
它總是3位數字,然後可選字符加數字? – jarlh
是的,除了最後的數字可以是一個或兩個數字。 – Lisa