2010-08-13 34 views
11

我在想我們之間的SQL天才能否幫助我。如何對「版本號」列一般使用SQL Server查詢進行排序

我有一個表Versions包含像

VersionNo 
--------- 
1.2.3.1 
1.10.3.1 
1.4.7.2 

我期待解決這「版本號」值的列VersionNo,但不幸的是,當我做一個標準的order by ,它被視爲一個字符串,所以訂單出來作爲

VersionNo 
--------- 
1.10.3.1 
1.2.3.1 
1.4.7.2 

Intead下面,這是wha T I是後:

VersionNo 
--------- 
1.2.3.1 
1.4.7.2 
1.10.3.1 

所以,我需要做的是通過以相反的順序號排序(例如在a.b.c.d中,我需要按d,c,b,a進行排序以得到正確的排序工具)。

但我堅持如何以通用的方式實現這一點。當然,我可以使用各種sql函數分割字符串(例如left,right,substring,len,charindex),但我不能保證版本號總會有4個部分。我可能有這樣的列表:

VersionNo 
--------- 
1.2.3.1 
1.3 
1.4.7.2 
1.7.1 
1.10.3.1 
1.16.8.0.1 

可以,有沒有人有任何建議?您的幫助將不勝感激。

+0

在最後一種情況,你想如何排序,因爲你沒有4件東西可以排序? – gbn 2010-08-13 07:50:46

+0

看來。那是我的問題,如果它被修復了,那將是一件輕而易舉的事。 – 2010-08-13 07:54:12

回答

18

如果您正在使用SQL Server 2008

select VersionNo from Versions order by cast('/' + replace(VersionNo , '.', '/') + '/' as hierarchyid); 

What is hierarchyid

編輯:

2000,2005,2008的解決方案:Solutions to T-SQL Sorting Challenge here

The challenge

+0

會是這樣嗎?但不幸的是,我被舊的SQL 2000卡住了。 – 2010-08-13 07:57:32

+0

@James Wiseman:在鏈接中你應該爲你找到解決方案。 – 2010-08-13 08:03:57

+0

輝煌!謝謝您的幫助。嘗試了它,它的工作原理。 – 2010-08-13 08:07:03

0

如果可以,請更改模式,以使版本具有4列而不是一列。然後排序很容易。

+0

哈哈,是的,不幸的是,這不是一種選擇。另外,長度可能是可變的,我不能保證列的最大數量是4或者其他任何東西。 – 2010-08-13 07:48:11

+0

如果您正在使用SQL Server 2005(可能是2008,需要仔細檢查)或更新版本,則可以編寫.NET CLR方法來進行比較,或更好地將任意版本號轉換爲規範的,可排序的格式(例如,填充每個部分,例如5位數字);將此CLR方法註冊到您的數據庫中,您可以將其稱爲常規SQL函數。否則,你一直堅持在SQL中實現相同的功能,這可能對你的性能不利。 – tdammers 2010-08-13 07:52:31

+0

是的,不幸的是,它是一個VB6和SQL 2000中的老內部應用程序。 – 2010-08-13 08:00:57

3

根據MySQL的SQL引擎將是某事像這樣:

SELECT versionNo FROM Versions 
ORDER BY 
SUBSTRING_INDEX(versionNo, '.', 1) + 0, 
SUBSTRING_INDEX(SUBSTRING_INDEX(versionNo, '.', -3), '.', 1) + 0, 
SUBSTRING_INDEX(SUBSTRING_INDEX(versionNo, '.', -2), '.', 1) + 0, 
SUBSTRING_INDEX(versionNo, '.', -1) + 0;

對於MySQL 3.23.15版本高於

 
SELECT versionNo FROM Versions ORDER BY INET_ATON(ip); 
+0

它的SQL Server作爲標記指示,但相應地更新了我的問題。 – 2010-08-13 07:56:06

+0

最後一個有效的解決方案,謝謝!請注意,如果數字不是全部小於256,那麼'INET_ATON'不能很好地工作。 – Paul 2015-09-19 13:48:08

1

另一種方式來做到這一點:

假設你只有A,B,C,D只可能以及數據輸出到列分離,並通過做一個順序,B, c,d(全部desc)並得到前1排

如果您需要縮放到d以上來說e,f,g ...只是改變1,2,3,4,以1,2,3,4,5,6,7等查詢

查詢: see demo

create table t (versionnumber varchar(255)) 
insert into t values 
('1.0.0.505') 
,('1.0.0.506') 
,('1.0.0.507') 
,('1.0.0.508') 
,('1.0.0.509') 
,('1.0.1.2') 


; with cte as 
(
    select 
    column1=row_number() over (order by (select NULL)) , 
    column2=versionnumber 
    from t 
    ) 

select top 1 
    CONCAT([1],'.',[2],'.',[3],'.',[4]) 
from 
(
    select 
     t.column1, 
     split_values=SUBSTRING(t.column2, t1.N, ISNULL(NULLIF(CHARINDEX('.',t.column2,t1.N),0)-t1.N,8000)), 
     r= row_number() over(partition by column1 order by t1.N) 
    from cte t 
     join 
     (
      select 
       t.column2, 
       1 as N 
      from cte t 
       UNION ALL 
      select 
       t.column2, 
       t1.N + 1 as N 
      from cte t 
       join 
       (
       select 
        top 8000 
         row_number() over(order by (select NULL)) as N 
       from 
        sys.objects s1 
         cross join 
        sys.objects s2 
       ) t1 
      on SUBSTRING(t.column2,t1.N,1) = '.' 
     ) t1 
      on t1.column2=t.column2 
)a 
pivot 
( 
    max(split_values) for r in ([1],[2],[3],[4]) 
    )p 
    order by [1] desc,[2] desc,[3] desc,[4] desc 
相關問題