2011-07-28 10 views
7

Tôi cần tìm cách lấy dữ liệu có phiên bản cao nhấtNumber.Tách một chuỗi và trả về số lớn nhất trong mssql

Đây là thiết kế cơ sở dữ liệu của tôi:

VERSIONNUMBER - varchar(15) 
DOWNLOADPATH - varchar(100) 

phép nói rằng tôi có hồ sơ như:

VERSIONNUMBER -------- DOWNLOADPATH 
1.1.2     a.com 
1.1.3     b.com 
2.1.4     c.com 
2.1.5     d.com 
2.2.1     e.com 

tôi cần để có được những kỷ lục với VERSIONNUMBER 2.2.1. Cần giúp đỡ với sql dù :)

Cảm ơn bạn đã giúp đỡ bất kỳ

Trả lời

4

Hãy thử điều này:

with a as 
(
    select * from (values 
    ('1.1.2'),('1.1.3'),('2.1.4 '), ('2.1.5'), ('2.2.1')) as b(c) 
) 
select c, PARSENAME(c,1),PARSENAME(c,2), PARSENAME(c,3) 
from a 
order by 
convert(int,PARSENAME(c,3)), 
convert(int,PARSENAME(c,2)), 
convert(int,PARSENAME(c,1)) 

Lấy cảm hứng từ: http://www.sql-server-helper.com/tips/sort-ip-address.aspx

with a as 
(
    select * from (values 
    ('1.1.2'),('1.1.3'),('2.1.4 '), ('2.1.5'), ('2.2.1')) as b(c) 
), 
x as 
(
    select c, 
     convert(int,PARSENAME(c,3)) * 100 
     + convert(int,PARSENAME(c,2)) * 10 
     + convert(int,PARSENAME(c,1)) * 1 as the_value 
    from a 
) 
select c from x where the_value = (select MAX(the_value) from x) 

Trong phát triển phần mềm, nó là điển hình để tìm một số phiên bản nhỏ mà có hai chữ số trong đó, số của phiên bản don' t có bất kỳ giá trị nào với giá trị của số, do đó phiên bản 1.12 lớn hơn 1.5; để bù đắp cho điều đó, bạn phải pad các chữ số đầy đủ:

-- Use this, the query above is not future-proof :-) 
with a as 
(
    select * from (values 
    ('2.1.4 '), ('2.1.12'), ('2.1.5'), ('2.2.1')) as b(c) 
), 
x as 
(
    select c, 
     convert(int,PARSENAME(c,3)) * 100*100*100 
     + convert(int,PARSENAME(c,2)) * 100*100 
     + convert(int,PARSENAME(c,1)) * 100 as the_value 
    from a 
) 
select c, the_value from x 
order by the_value 

Output:

2.1.4 2010400 
2.1.5 2010500 
2.1.12 2011200 
2.2.1 2020100 

Nếu bạn không đi mà vào xem xét (như với các truy vấn sau đây):

with a as 
(
    select * from (values 
    ('2.1.4 '), ('2.1.12'), ('2.1.5'), ('2.2.1')) as b(c) 
), 
x as 
(
    select c, 
     convert(int,PARSENAME(c,3)) * 100 
     + convert(int,PARSENAME(c,2)) * 10 
     + convert(int,PARSENAME(c,1)) * 1 as the_value 
    from a 
) 
select c, the_value from x 
order by the_value; 


    -- KorsG's answer has a bug too 
with a as 
(
    select * from (values 
    ('2.1.4 '), ('2.1.12'), ('2.1.5'), ('2.2.1')) as b(c) 
), 
x as 
(
    select c, 
     CAST(REPLACE(c, '.', '') AS int) as the_value 
    from a 
) 
select c, the_value from x 
order by the_value  

Hai truy vấn này sẽ mang lại kết quả tương tự (không chính xác):

c   the_value 
2.1.4 214 
2.1.5 215 
2.2.1 221 
2.1.12 222 

Giá trị của 2.2.1 và 2.1.12 trùng lặp. Điều đó cũng xảy ra khi bạn chỉ xóa các chấm và chuyển trực tiếp chuỗi kết quả thành int. 2.1.12 trở thành hai nghìn một trăm mười hai, 2.2.1 trở thành hai trăm hai mươi mốt người. 2.2.1 lớn hơn 2.1.12, không nhỏ hơn

+0

Nhân các bộ phận và thêm chúng làm thủ thuật. Cảm ơn bạn – Pabuc

-2
SELECT downloadpath FROM TABLE 
WHERE versionnumber = (SELECT MAX(VersionNumber) FROM TABLE) 

Có thể có một cách đẹp hơn để làm điều đó là tốt.

+0

Theo như tôi biết, MAX chỉ hoạt động với int, vì vậy không thể làm tối đa cho 3.1.4. – Pabuc

+0

Nó hoạt động tốt trên SQL Server. – DavveK

+0

Pabuc, nó hoạt động với chuỗi. Chỉ cần thử nghiệm nó trên MySQL. –

2
select top 1 DOWNLOADPATH 
from YourTable 
order by cast(parsename(VERSIONNUMBER, 3) as int) desc, 
     cast(parsename(VERSIONNUMBER, 2) as int) desc, 
     cast(parsename(VERSIONNUMBER, 1) as int) desc 
+1

Sự chiếm đoạt tuyệt vời một chức năng hiện có :) –

0

Điều này sẽ hiệu quả, nhưng không đẹp - tôi chắc chắn sẽ xem xét thay đổi cách bạn lưu trữ số phiên bản.

concat( 
right(concat(repeat("0",5), substring_index(VERSIONNUMBER,".",1)),5), 
right(concat(repeat("0",5), substring_index(substring_index(VERSIONNUMBER,".",2),".",-1)),5), 
right(concat(repeat("0",5), substring_index(VERSIONNUMBER,".",-1)),5)) 

Về cơ bản nó quay "1.24.937" vào "000010002400937", sau đó phân loại đúng như là một chuỗi.

1

Ngoài ra, thay vì nhân mỗi nhóm chữ số, bạn có thể sử dụng bảng xếp hạng:

with a as 
(
    select * from (values 
     ('2.1.4 '), ('2.1.12'), ('2.1.5'), ('2.2.1') 
    ) as b(c)  
), 
x as 
(
select c, 
    Ranking = RANK() over(order by convert(int,PARSENAME(c,3)), convert(int,PARSENAME(c,2)), convert(int,PARSENAME(c,1))) 
from a 
) 
select * from x 
    order by ranking 

Sản lượng:

c Ranking 
2.1.4 1 
2.1.5 2 
2.1.12 3 
2.2.1 4 

cuối cùng truy vấn:

with a as 
(
    select * from (values 
     ('2.1.4 '), ('2.1.12'), ('2.1.5'), ('2.2.1') 
    ) as b(c)  
), 
x as 
(
select c, 
    Ranking = RANK() over(order by convert(int,PARSENAME(c,3)), convert(int,PARSENAME(c,2)), convert(int,PARSENAME(c,1))) 
from a 
) 
select * 
from x 
where Ranking = (select MAX(ranking) from x) 

Output:

c Ranking 
2.2.1 4 

Một phương pháp đơn giản, sắp xếp giảm dần sau đó chỉ nhận được dòng đầu tiên:

with a as 
(
    select * from (values 
     ('2.1.4 '), ('2.1.12'), ('2.1.5'), ('2.2.1')) as b(c)  
), 
x as 
(
select c, 
    Ranking = RANK() 
     over(order by 
      convert(int,PARSENAME(c,3)) desc, 
      convert(int,PARSENAME(c,2)) desc, 
      convert(int,PARSENAME(c,1)) desc) 
from a 
) 
select * 
from x 
where Ranking = 1 
0

Cá nhân, tôi thích @ phiên bản Mikael, nhưng rõ ràng đó không phải là khá cầm tay để RDBMSes khác ...

Làm thế nào về điều này? Nhanh chóng và dơ bẩn, và hoạt động cho các phiên bản ba số (như được đưa ra trong ví dụ của bạn.)

Việc hack ở đây là nhận ra rằng "2.59" là một số hợp lệ, không phải là số nguyên hợp lệ chỉ phải chia chuỗi ở một nơi - bạn muốn có số phiên bản chính và phần còn lại. Điều này thật ghê gớm, nhưng khi nó xuất hiện trong tâm trí, tôi nghĩ rằng tôi muốn chia sẻ nó, vì nó ít nhất là ngắn và ghê gớm.

SELECT 
    TOP 1 downloadpath 
FROM 
    version_table 
ORDER BY 
    CAST(LEFT(VERSIONNUMBER, CHARINDEX('.', VERSIONNUMBER) - 1) AS INTEGER) DESC, 
    CAST(SUBSTRING(VERSIONNUMBER, CHARINDEX('.', VERSIONNUMBER) + 1, 100) AS FLOAT) DESC 

Tất nhiên, câu trả lời thực sự là để thay đổi thiết kế cơ sở dữ liệu của bạn cho một trong hai tách ra những con số phiên bản hoặc bao gồm một số xây dựng hoặc một cái gì đó như thế ...

1

Nếu bạn đang ở trên SQL Server 2008 bạn có thể sử dụng kiểu dữ liệu HIERARCHYID.

SELECT VersionNumber, DownloadPath 
FROM (VALUES 
    ('1.1.2','a.com'), 
    ('1.1.3','b.com'), 
    ('2.1.4','c.com'), 
    ('2.1.5','d.com'), 
    ('2.2.1','e.com')   
    ) AS T(VersionNumber, DownloadPath) 
ORDER BY CAST('/' + VersionNumber + '/' AS HIERARCHYID) DESC 
+0

giải pháp thú vị với HIERARCHYID.Thanks;) –

Các vấn đề liên quan