มีการเปรียบเทียบเรียงลำดับสตริงต่อไปนี้ตามลำดับต่อไปนี้ 1,2,3,6,10,10A, 10B, 11 หรือไม่


12

ฉันมีฐานข้อมูลที่มีคอลัมน์ VARCHAR ที่มีจำนวนเต็มความยาวแตกต่างกัน ฉันต้องการจัดเรียงพวกเขาดังนั้น 10 มาหลังจาก 9 ไม่ใช่ 1 และ 70A มาหลังจาก 70 ฉันสามารถทำได้ด้วยPATINDEX () , คำสั่ง CTE และ CASE ในส่วนคำสั่ง WHERE

อย่างไรก็ตามฉันสงสัยว่ามีการเปรียบเทียบที่นี่จะไม่จำเป็น


นี่คือลิงค์ใหม่สำหรับคำแนะนำนั้นทันทีที่ Microsoft ได้โอนย้ายจาก Connect to UserVoice แล้ว แต่ยังไม่ได้ส่งต่อ URIs: สนับสนุน "การเรียงแบบธรรมชาติ" / DIGITSASNUMBERS เป็นตัวเลือกการเรียงลำดับ
โซโลมอน Rutzky

2
Microsoft ได้กล่าวว่าพวกเขาจะใช้สิ่งนี้เป็นคุณสมบัติในตัวใน SQL Server หากพวกเขาได้รับคะแนนเสียงเพียงพอ เพื่อไปกว่าที่นี่และคลิกที่ปุ่มโหวต
Peter Aylett

คำตอบ:


8

ไม่การจัดเรียงนั้นเกี่ยวกับการเรียงลำดับตัวอักษรโดยขึ้นอยู่กับโค้ดเพจ, สำเนียง, ตัวพิมพ์, ความกว้าง, kana อักขระตัวเลข (0-9) ไม่มีคุณสมบัติใด ๆ

ดังนั้น9อยู่เสมอหลังจากที่10Bในใด ๆเรียงลำดับ

คุณต้องแยกมันตามที่คุณจดบันทึกหรือเรียงลำดับเช่นนี้:

ORDER BY
    RIGHT('                              ' + MyColumn, 30)

ความยาวด้านขวาจะเป็นตัวกำหนดว่าคุณมีช่องว่างจำนวนเท่าใด

แน่นอนคุณสามารถ:

  • มี 2 ​​คอลัมน์เพื่อทำให้สิ่งนี้ไม่จำเป็น (และเร็วกว่า) และมีคอลัมน์ที่คำนวณเพื่อรวมเข้าด้วยกัน
  • ยืนยันค่าศูนย์นำหน้า
  • จัดชิดขวาในรูปถ่าน (รุ่นที่ถูกต้องของฉันด้านขวา)

ข้อเสนอแนะ 2 ข้อหลังเป็นเหมือนสิทธิของฉันด้านบนและแตกต่างกันเล็กน้อย จัดเรียงได้เร็วขึ้น (ไม่จำเป็นต้องประมวลผล colukmn) แต่ต้องการพื้นที่เก็บข้อมูลเพิ่มเติม


ฉันไม่เห็นวิธีการทำงาน มันแบ่งเป็น 2, 2a, 3, ฯลฯ ...
Mladen Prajdic

@ Laden Prajdic: ถูกต้องแล้วอ๊ะ ลืมเกี่ยวกับ alphabeticals ต่อท้าย
GBN

เกี่ยวกับ " ดังนั้น9อยู่เสมอ10Bในการเรียงลำดับใด ๆ ": เป็นวิธีเดียวใน SQL Server เนื่องจากตัวเลือกการเรียงลำดับต้นแบบเพื่อจัดการ "DigitsAsNumbers" ไม่ได้ถูกเปิดเผยเป็นตัวเลือกการจัดเรียง ยัง ;-) สิ่งนี้มีให้สำหรับแอพที่ใช้ Windows เริ่มต้นใน Windows 7 โดยเฉพาะอย่างยิ่งใน File Explorer และในหนึ่งวันสามารถสัมผัสกับ SQL Server ได้หากมีคนสนับสนุนแนวคิดนี้เพียงพอ ผมพยายามที่จะได้รับลูกบอลกลิ้งโดยยื่นข้อเสนอแนะที่เชื่อมต่อไปนี้: การสนับสนุน "การเรียงลำดับธรรมชาติ" / DIGITSASNUMBERS เป็นตัวเลือกเปรียบเทียบ
โซโลมอน Rutzky

8

ฉันจะตั้งค่าคอลัมน์ที่คำนวณแล้วเรียงลำดับตามนั้น สิ่งที่ต้องการ

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

จากนั้นใช้คอลัมน์นี้เพื่อจัดเรียงตามที่คุณสามารถจัดทำดัชนีคอลัมน์ได้


มันมีประโยชน์มากที่จะรู้เกี่ยวกับปัญหาที่คล้ายกัน อย่างไรก็ตามในกรณีนี้ฉันไม่สามารถเปลี่ยนสคีมาได้
Justin Dearing

คุณสามารถเพิ่มลงในสคีมาได้หรือไม่ นอกจากคอลัมน์ที่คำนวณแล้วคุณสามารถสร้างมุมมองได้ตลอดเวลาแม้ว่าจะไม่สามารถปรับให้เหมาะสมได้จริงเช่นคอลัมน์ที่คำนวณได้
แอรอนเบอร์ทรานด์ด์

หากคุณทำมุมมองที่จัดทำดัชนีและมีรุ่น Enterprise แบบสอบถามของคุณจะใช้มุมมองที่จัดทำดัชนีโดยอัตโนมัติหากสามารถหาสิ่งที่คุณพยายามที่จะทำ หากรุ่นมาตรฐานคุณต้องใช้ปุ่ม WITH (NOEXPAND) เพื่อทริกเกอร์มุมมองที่จัดทำดัชนีไว้ ณ จุดนี้คุณจะต้องมีคำสั่งกรณีในการสั่งซื้อของคุณ แต่มันควรจะทำงานฉันคิดว่า
mrdenny

คุณไม่จำเป็นต้องสร้างคอลัมน์จากการคำนวณ คุณสามารถใช้นิพจน์นั้นโดยตรงในข้อ ORDER BY
a_horse_with_no_name

หากคุณต้องการรับประกันการสแกนดัชนีหรือตารางคุณสามารถทำได้ หากคุณต้องการให้สามารถจัดทำดัชนีค่าได้จำเป็นต้องใช้คอลัมน์หรือมุมมองที่คำนวณแล้ว
mrdenny

5

หากคุณต้องการวิธีที่เจ็บปวดในการพิสูจน์สิ่งที่ @gbn พูด (โดยหลักแล้วว่าคุณไม่สามารถบอกให้เรียงลำดับของสตริงย่อยต่างกันได้) คุณสามารถสร้างตาราง #temp ด่วนที่มีค่าสัมประสิทธิ์ตามที่คุณคาดหวังและดูว่า การเรียงลำดับโดยการเปรียบเทียบใด ๆ จะส่งคืนคำสั่งเดิม:

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;

สิ่งนี้จะทำงานสำหรับฉันในเวลาประมาณ 10 วินาทีและให้ผลตอบแทน 0 แถว - หมายถึงไม่มีการเปรียบเทียบกับ SQL Server (อย่างน้อย 2008 R2 ไม่ได้ลอง Denali) จะเรียงลำดับตามที่คุณคาดหวัง คุณต้องใช้วิธีอื่นในการกำหนดการเรียงลำดับ


2

ต้องการวิธีการเรียงลำดับตัวเลขในสตริงที่สมเหตุสมผลและสมเหตุสมผล พิจารณาการลงคะแนนสำหรับคำแนะนำ Microsoft Connect ของฉัน: สนับสนุน "การเรียงลำดับโดยธรรมชาติ" / DIGITSASNUMBERS เป็นตัวเลือกการจัดเรียง


ในขณะที่คำถามนี้เฉพาะกับ SQL Server และคำตอบนี้ไม่ได้ฉันรู้สึกว่าฉันควรโพสต์ข้อมูลนี้เพียงเพื่อสร้างความตระหนักรู้และไม่ขัดต่อคำตอบอื่น ๆ

ดังที่กล่าวไว้ภายนอก SQL Server ในบางสภาพแวดล้อมคุณสามารถทำการเรียงลำดับได้ เป็นสิ่งที่ระบุไว้อย่างน้อยในเอกสาร Unicode ในUNICODE LOCALE DATA MARKUP LANGUAGE (LDML) ส่วนที่ 5: การรวบรวมมาตรฐาน / รายงานมีแผนภูมิสำหรับการตั้งค่าการเรียงที่อธิบายตัวเลือกต่าง ๆ สำหรับการปรับแต่งพฤติกรรมการเรียงลำดับ หนึ่งในตัวเลือกคือ-kn-trueหรือ[numericOrdering on]:

หากตั้งค่าเป็นเปิดลำดับเลขฐานสิบใด ๆ (General_Category = Nd ใน [ UAX44 ]) จะถูกจัดเรียงในระดับหลักพร้อมค่าตัวเลข ตัวอย่างเช่น "A-21" <"A-123" น้ำหนักหลักที่คำนวณได้ทั้งหมดอยู่ที่จุดเริ่มต้นของกลุ่มการเรียงลำดับตัวเลขใหม่ ดังนั้นด้วยตาราง UCA ที่ไม่มีการตัดทอน "a $" <"a0" <"a2" <"a12" <"a⓪" <"aa"

อย่างไรก็ตามเอกสารนี้เป็น "มาตรฐานทางเทคนิค" และไม่ใช่ส่วนหนึ่งของข้อมูลจำเพาะ Unicode หลัก หมายเหตุที่ด้านบนสุดของเอกสารระบุ:

มาตรฐานทางเทคนิค Unicode (UTS)เป็นข้อกำหนดเฉพาะ ความสอดคล้องกับมาตรฐาน Unicode ไม่ได้บ่งบอกถึงความสอดคล้องกับ UTS ใด ๆ

ดังนั้นลักษณะการทำงานนี้โดยเฉพาะจะไม่สามารถใช้ได้ใน SQL Server หรือแม้แต่ใน. NET (อย่างน้อยก็ไม่ได้โดยกำเนิด) แม้ว่าทั้งสองจะเป็นไปตามข้อกำหนดของ Unicode หลัก

ICUโครงการ (ส่วนประกอบระหว่างประเทศเพื่อการ Unicode) เป็นชุดของ C / C ++ และห้องสมุด Java ที่ดำเนินการทำงานนี้และมีแม้กระทั่งการสาธิตออนไลน์ของมัน และภายใต้ "โปรเจ็กต์ที่เกี่ยวข้อง" มีลิงก์ไปยังโปรเจ็กต์. NET ที่ดูเหมือนจะเป็นตัวห่อวัตถุ COM สำหรับไลบรารี ICU ที่จะอนุญาตให้ฟังก์ชันนี้เปิดเผยรหัสที่ได้รับการจัดการ แต่ไม่ชัดเจนว่าโครงการ. NET นั้นยังคงทำงานอยู่

แต่การที่จะเห็นพฤติกรรมนี้ในการดำเนินการไปที่ห้องไอซียู Collation สาธิต

วางสิ่งต่อไปนี้ลงในพื้นที่ป้อนข้อความทางด้านซ้าย:

1
2
10B
6
11
10A
3
10

ตั้งค่าตัวเลือกทั้งหมดเป็น "ค่าเริ่มต้น" ตรวจสอบตัวเลือก "หมายเลขบรรทัดอินพุต" ทางด้านขวาของsortปุ่มและตรวจสอบให้แน่ใจว่าไม่ได้เลือกตัวเลือก "จุดแข็งต่าง"

คลิกที่sortปุ่มและคุณควรจะได้รับสิ่งต่อไปนี้:

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

นี่คือสิ่งที่ควรคาดหวังเมื่อทำการเรียงลำดับสตริงทั่วไปและสิ่งที่คุณเห็นใน SQL Server

ตอนนี้ในชุดของปุ่มตัวเลือกที่อยู่เหนือsortปุ่มแถวที่สองจะมีป้ายกำกับว่า "ตัวเลข" เลือกปุ่มตัวเลือก "เปิด"

คลิกที่sortปุ่มอีกครั้งและคุณควรได้รับสิ่งต่อไปนี้:

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

การตั้งคำถามถ้าสิ่งนี้ใช้งานได้หรือไม่เมื่อส่วนที่เป็นตัวเลขอยู่กลางสตริง? ตกลงวางสิ่งต่อไปนี้ลงในพื้นที่ป้อนข้อความทางด้านซ้าย (แทนที่รายการก่อนหน้า):

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

ตรวจสอบให้แน่ใจว่าการตั้งค่าตัวเลขยังคงเป็น "เปิด" คลิกที่sortปุ่มอีกครั้งและคุณควรได้รับสิ่งต่อไปนี้:

[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

ต้องการเห็นสิ่งนี้ในที่อื่นไหม สร้างโฟลเดอร์บนฮาร์ดไดรฟ์ของคุณเช่นC: \ temp \ sorting \และสร้างไฟล์เปล่าที่มีชื่อ "Script -... " เหมือนกัน ทำDIRในหน้าต่างคำสั่งและคุณจะเห็นการเรียงลำดับมาตรฐาน แต่เมื่อดูรายการไฟล์ใน Windows Explorer คุณจะเห็นรายการเรียงลำดับโดยใช้ตัวเลือก "ตัวเลข" :-)


FYI, Postgres 10 ได้รับการสนับสนุนสำหรับการเปรียบเทียบ ICU ดูโพสต์บล็อกนี้โดย Peter Eisentraut
Basil Bourque

@BasilBourque ขอบคุณที่พูดถึงเรื่อง PG10 โพสต์บล็อกนั้นในตอนท้ายระบุว่า "ICU มีฟังก์ชันการทำงานจำนวนมากในพื้นที่นี้ซึ่งเรายังไม่เปิดเผยผ่าน PostgreSQL ยังมีตัวเลือกสำหรับการเรียงลำดับตัวพิมพ์เล็กและตัวพิมพ์ใหญ่การเรียงลำดับสำเนียงที่ไม่รู้สึกตัว สำหรับผู้ที่ต้องการเผยแพร่ PostgreSQL ในอนาคต " ดังนั้นในการใช้งานครั้งแรก / ปัจจุบันมันจะไม่เปลี่ยนแปลงข้อมูลใด ๆ ในคำตอบของฉัน หากข้อเสนอในอนาคตอนุญาตให้มีการเรียงลำดับตัวเลขฉันจะกล่าวถึงในคำตอบของฉัน แต่เป็นเชิงอรรถเนื่องจากคำถามนี้เป็นเฉพาะ SQL Server
โซโลมอน Rutzky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.