Có đối chiếu để sắp xếp các chuỗi sau theo thứ tự sau 1,2,3,6,10,10A, 10B, 11 không?


12

Tôi có một cơ sở dữ liệu với cột VARCHAR chứa các số nguyên có độ dài khác nhau. Tôi muốn sắp xếp chúng sao cho 10 đến sau 9, không phải 1 và 70A đến sau 70. Tôi đã có thể làm điều này với các câu lệnh PATINDEX () , CTE và CASE trong mệnh đề WHERE.

Tuy nhiên, tôi đã tự hỏi nếu có một đối chiếu mà điều này sẽ không cần thiết.


Đây là liên kết mới cho đề xuất đó bây giờ rằng Microsoft đã di chuyển từ Connect sang UserVoice nhưng không chuyển tiếp URI: Hỗ trợ "sắp xếp tự nhiên" / DIGITSASNUMBERS dưới dạng tùy chọn Đối chiếu
Solomon Rutzky

2
Microsoft đã nói rằng họ sẽ triển khai tính năng này như một tính năng tích hợp trong SQL Server nếu họ nhận được đủ số phiếu. Vì vậy, đi qua đây và bấm vào nút bỏ phiếu .
Peter Aylett

Câu trả lời:


8

Không đối chiếu là về sắp xếp theo thứ tự chữ cái, tùy thuộc vào trang mã, dấu, trường hợp, chiều rộng, kana. Số ký tự (0-9) không có thuộc tính nào trong đó.

Vì vậy, 9luôn luôn là sau 10Btrong bất kỳ loại.

Bạn phải chia nó ra như bạn đã lưu ý hoặc sắp xếp như thế này:

ORDER BY
    RIGHT('                              ' + MyColumn, 30)

Độ dài ở bên phải xác định bạn có bao nhiêu khoảng trống.

Tất nhiên bạn có thể:

  • có 2 cột để làm điều này không cần thiết (và nhanh hơn nhiều) và có một cột được tính để kết hợp chúng
  • nhấn mạnh vào số không hàng đầu
  • quyền biện minh trong một char (phiên bản được lưu trữ của QUYỀN của tôi ở trên)

Hai gợi ý sau giống như QUYỀN của tôi ở trên và hơi khác nhau. Sắp xếp nhanh hơn (không cần xử lý colukmn cần thiết) nhưng cần thêm dung lượng


tôi không thấy nó hoạt động như thế nào Nó nghỉ trong 2, 2a, 3, v.v ...
Mladen Prajdic

@Mladen Prajdic: bạn đúng rồi, rất tiếc. Quên về các chữ cái theo sau
gbn

Về " Vì vậy, 9luôn luôn là sau 10Bbất kỳ loại nào. ": Chỉ có cách đó trong SQL Server vì tùy chọn sắp xếp cơ bản để xử lý "DigitsAsNumbers" chưa được hiển thị dưới dạng tùy chọn Đối chiếu. Chưa ;-). Điều này đã có sẵn cho các ứng dụng dựa trên Windows bắt đầu trong Windows 7, đáng chú ý nhất là trong File Explorer. Và một ngày nào đó nó có thể được tiếp xúc với SQL Server, nếu đủ người ủng hộ ý tưởng này. Tôi đã cố gắng làm cho quả bóng lăn bằng cách gửi gợi ý Kết nối sau: Hỗ trợ "sắp xếp tự nhiên" / DIGITSASNUMBERS làm tùy chọn Đối chiếu .
Solomon Rutzky

8

Tôi sẽ thiết lập một cột được tính toán sau đó sắp xếp dựa trên đó. Cái gì đó như

CAST( 
     CASE WHEN IS_NUMERIC(left(OtherColumn, 2) = 1) then 
         left(OtherColumn,2) 
     else 
         left(otherColumn, 1)  
AS INT)

Sau đó sử dụng cột này để sắp xếp theo như bây giờ bạn có thể lập chỉ mục cột.


Điều đó thực sự hữu ích để biết về các vấn đề tương tự. Tuy nhiên, trong trường hợp này tôi không thể thay đổi lược đồ.
Justin thân mến

Bạn có thể thêm vào lược đồ? Chặn một cột được tính toán, bạn luôn có thể tạo chế độ xem - mặc dù điều này sẽ không thực sự tối ưu như cột được tính toán.
Aaron Bertrand

Nếu bạn thực hiện chế độ xem được lập chỉ mục và có phiên bản Enterprise, truy vấn của bạn sẽ tự động sử dụng chế độ xem được lập chỉ mục nếu nó có thể tìm ra những gì bạn đang cố gắng thực hiện. Nếu phiên bản tiêu chuẩn, bạn cần sử dụng VỚI (NOEXPAND) để kích hoạt chế độ xem được lập chỉ mục sẽ được sử dụng. Tại thời điểm đó, bạn cần phải có tuyên bố trường hợp theo thứ tự của bạn nhưng nó sẽ hoạt động, tôi nghĩ vậy.
mrdenny

Bạn không cần tạo một cột được tính toán. Bạn có thể sử dụng biểu thức đó trực tiếp trong mệnh đề ORDER BY
a_horse_with_no_name

Nếu bạn muốn đảm bảo quét chỉ mục hoặc quét bảng chắc chắn bạn có thể. Nếu bạn muốn có thể lập chỉ mục giá trị thì cần có một cột được tính toán hoặc chế độ xem được lập chỉ mục.
mrdenny

5

Nếu bạn muốn một cách đau đớn để chứng minh những gì @gbn đang nói (về cơ bản là bạn không thể nói đối chiếu để đặt hàng các chuỗi khác nhau), bạn có thể tạo một bảng #temp nhanh có hệ số cho đơn hàng bạn mong đợi và xem đặt hàng bởi bất kỳ đối chiếu nào trả về cùng một thứ tự:

CREATE TABLE #foo(id INT, n NVARCHAR(10));

CREATE TABLE #bar(collation SYSNAME);

SET NOCOUNT ON;

INSERT #foo SELECT 1,'1'
UNION SELECT 2,'2'
UNION SELECT 3,'3'
UNION SELECT 4,'6'
UNION SELECT 5,'10'
UNION SELECT 6,'10A'
UNION SELECT 7,'10B'
UNION SELECT 8,'11';

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'
    WITH x AS 
    (
        SELECT n, rn = ROW_NUMBER() OVER 
        (ORDER BY n COLLATE ' + name + ') FROM #foo
    ) 
    INSERT #bar 
    SELECT TOP (1) ''' + name + ''' FROM x
    WHERE NOT EXISTS
    (
        SELECT COUNT(*) FROM #foo AS f
        WHERE f.id = x.rn
        AND f.n <> x.n
    );' FROM sys.fn_helpcollations();

EXEC sp_executesql @sql;

SELECT collation FROM #bar;

GO
DROP TABLE #foo, #bar;

Điều này chạy cho tôi trong khoảng 10 giây và mang lại 0 hàng - có nghĩa là không có đối chiếu có sẵn cho SQL Server (ít nhất là 2008 R2, chưa thử Denali) sẽ sắp xếp theo cách bạn mong đợi. Bạn cần một cách khác để xác định sắp xếp.


2

Bạn muốn một phương tiện hợp lý, hiệu quả để sắp xếp các số trong chuỗi là số thực? Xem xét bỏ phiếu cho đề xuất Microsoft Connect của tôi: Hỗ trợ "sắp xếp tự nhiên" / DIGITSASNUMBERS làm tùy chọn Đối chiếu


Mặc dù Câu hỏi này dành riêng cho SQL Server và Câu trả lời này thì không, tôi cảm thấy rằng tôi vẫn nên đăng thông tin này đơn giản để nâng cao nhận thức về nó và không phản đối bất kỳ câu trả lời nào khác.

Điều đó đang được nói, bên ngoài SQL Server, trong một số môi trường nhất định có thể thực hiện kiểu sắp xếp này. Đó là một cái gì đó ít nhất được chỉ định trong tài liệu Unicode. Trong NGÔN NGỮ DỮ LIỆU DỮ LIỆU DỮ LIỆU (LDML) UNICODE PHẦN 5: Tiêu chuẩn / báo cáo THU , có một biểu đồ cho Cài đặt đối chiếu mô tả các tùy chọn khác nhau để điều chỉnh hành vi sắp xếp. Một trong các tùy chọn là -kn-truehoặc [numericOrdering on]:

Nếu được đặt thành bật , bất kỳ chuỗi Số thập phân nào (General_Carget = Nd trong [ UAX44 ]) được sắp xếp ở cấp chính với giá trị số của nó. Ví dụ: "A-21" <"A-123". Các trọng số chính được tính toán là tất cả khi bắt đầu nhóm sắp xếp lại chữ số . Do đó, với bảng UCA chưa được bảo vệ, "a $" <"a0" <"a2" <"a12" <"a⓪" <"aa".

Tuy nhiên, tài liệu này là "tiêu chuẩn kỹ thuật" và không phải là một phần của đặc tả Unicode cốt lõi. Một ghi chú ở đầu tài liệu nêu rõ:

Tiêu chuẩn kỹ thuật Unicode (UTS) là một đặc điểm kỹ thuật độc lập. Sự phù hợp với Tiêu chuẩn Unicode không bao hàm sự phù hợp với bất kỳ UTS nào.

Do đó, hành vi cụ thể này không có sẵn trong SQL Server hoặc thậm chí trong .NET (ít nhất là không nguyên bản), mặc dù cả hai đều tuân thủ đặc tả Unicode cốt lõi.

các ICU dự án (Components International cho Unicode) là một tập hợp của C / C ++ và Java thư viện mà cụ chức năng này, và thậm chí còn có một bản demo trực tuyến của nó. Và trong "các dự án liên quan", có một liên kết đến một dự án .NET dường như là một trình bao bọc đối tượng COM cho thư viện ICU cho phép chức năng này được hiển thị với mã được quản lý. Nhưng không rõ dự án .NET đó có còn hoạt động không.

Nhưng để thấy hành vi này hoạt động, hãy đến ICU Collation Demo .

Dán phần sau vào vùng văn bản Nhập ở phía bên trái:

1
2
10B
6
11
10A
3
10

Đặt tất cả các tùy chọn thành "mặc định". Kiểm tra tùy chọn "số dòng đầu vào" ở bên phải củasort nút và đảm bảo rằng tùy chọn "độ mạnh khác biệt" không được kiểm tra.

Nhấp vào sortnút và bạn sẽ nhận lại được những điều sau đây:

[1] 1
[8] 10
[6] 10A
[3] 10B
[5] 11
[2] 2
[7] 3
[4] 6

Đây là những gì nên được mong đợi khi thực hiện sắp xếp chuỗi điển hình và những gì bạn đang thấy trong SQL Server.

Bây giờ, trong loạt các nút radio ngay phía trên sortnút, hàng thứ hai được gắn nhãn "số". Chọn nút radio "bật".

Nhấp vào sortnút một lần nữa và bạn sẽ nhận lại như sau:

[1] 1
[2] 2
[7] 3
[4] 6
[8] 10
[6] 10A
[3] 10B
[5] 11

Câu hỏi nếu điều này hoạt động khi phần số ở giữa chuỗi? Ok, dán phần sau vào vùng văn bản Nhập ở bên trái (thay thế danh sách trước):

Script - 1.sql
Script - 2.sql
Script - 10B.sql
Script - 6.sql
Script - 11.sql
Script - 10A.sql
Script - 3.sql
Script - 10.sql

Đảm bảo rằng cài đặt số vẫn được đặt thành "bật". Nhấp vào sortnút một lần nữa và bạn sẽ nhận lại như sau:

[1] Script - 1.sql
[2] Script - 2.sql
[7] Script - 3.sql
[4] Script - 6.sql
[8] Script - 10.sql
[6] Script - 10A.sql
[3] Script - 10B.sql
[5] Script - 11.sql

Bạn muốn thấy điều này ở một nơi khác? Tạo một thư mục trên ổ cứng của bạn, một cái gì đó như C: \ temp \ sorting \ và tạo các tệp trống có cùng tên "Script -...". Thực hiện DIRtrong một cửa sổ lệnh và bạn sẽ thấy sắp xếp tiêu chuẩn. Nhưng khi nhìn vào danh sách các tệp trong Windows Explorer, bạn sẽ thấy danh sách được sắp xếp bằng tùy chọn "số" :-).


FYI, Postgres tăng 10 hỗ trợ cho các hợp đồng ICU. Xem bài đăng trên blog này của Peter Eisentraut.
Basil Bourque

@BasilBourque Cảm ơn bạn đã đề cập đến điều đó về PG10. Cuối cùng, bài đăng trên blog đó nói rằng "ICU cung cấp rất nhiều chức năng trong lĩnh vực này mà chúng tôi chưa thể hiện thông qua PostgreQuery. Có các tùy chọn để sắp xếp không phân biệt chữ hoa chữ thường, phân loại không nhạy cảm và hoàn toàn tùy chỉnh đối chiếu. cho những người phát hành PostgreSQL trong tương lai. " Vì vậy, trong lần thực hiện đầu tiên / hiện tại, nó không thay đổi bất kỳ thông tin nào trong câu trả lời của tôi. Nếu một đề nghị trong tương lai không cho phép sắp xếp số, thì tôi sẽ đề cập đến nó trong câu trả lời của mình, nhưng như một chú thích vì câu hỏi này là dành riêng cho SQL Server.
Solomon Rutzky
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.