ทำไมระหว่างของ SQL รวมมากกว่าเปิดครึ่ง?


45

Semi-open (หรือ Half-Open, Half-Closed , Half-Bounded ) ช่วงเวลา ( [a,b)ซึ่งxเป็นของ iff ช่วงเวลาa <= x < b) เป็นเรื่องธรรมดาในการเขียนโปรแกรมเนื่องจากมีคุณสมบัติที่สะดวกมากมาย

ใครสามารถเสนอเหตุผลที่อธิบายว่าทำไม SQL BETWEENใช้ช่วงปิด ( [a,b])? นี่คือ esp ไม่สะดวกสำหรับวันที่ ทำไมคุณถึงBETWEENทำตัวแบบนี้


ฉันอยากรู้อยากเห็นพวกเขามีคุณสมบัติอะไรที่สะดวกสบาย?
phant0m

2
ถ้ามันไม่รวมวิธีการที่คุณสามารถค้นหาชื่อสุดท้ายทั้งหมดในช่วง A ถึง D ได้อย่างง่ายดาย? หรือชื่อ W ถึง Z สำหรับตัวเลขระหว่าง 1 ถึง 10 คุณสามารถค้นหา 0 <n <11 แต่สำหรับอักขระที่คุณต้องใช้หมายเลข ASCII? หรือหมายเลข Unicode? นอกจากนี้ดัชนียังช่วยให้คุณเริ่มต้นข้อมูลได้อย่างง่ายดาย
jqa

2
ฉันเข้าใจความคับข้องใจของคุณ (StartDate> = '2010-01-01' และ StartDate <'2011-01-01') ใช้งานได้อย่างสวยงามเพื่อใช้งานระหว่าง equivelent (StartDate ระหว่าง '2010-01-01' และ ' 2010-12-31 23:59:59 ') ทั้งใหญ่และต้องรู้ว่ากี่วันใน ธ.ค.
ทอดด์

1
@ phant0m [a, b) U [c, d) == [a, d) [a: int, b: int) มีองค์ประกอบ ba อย่างแน่นอน ความคิดเห็นของทอดด์แสดงให้เห็นว่าพวกเขาทำงานได้ดีเป็นพิเศษสำหรับวันที่ (ซึ่งฉันคิดถึงพวกเขามากที่สุด) โดยทั่วไปเมื่อมีการเข้ารหัสช่วงเวลากึ่งเปิดมักจะง่ายขึ้นใช้งานง่ายขึ้นและมีประสิทธิภาพ
alex

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

คำตอบ:


48

ฉันคิดว่าการรวมBETWEENนั้นง่ายกว่า (และเห็นได้ชัดว่านักออกแบบ SQL) มากกว่าช่วงเวลากึ่งเปิด ตัวอย่างเช่นถ้าฉันพูดว่า "เลือกตัวเลขระหว่าง 1 ถึง 10" คนส่วนใหญ่จะรวมหมายเลข 1 และ 10 ช่วงเวลาที่เปิดกว้างนั้นจริงแล้วทำให้สับสนสำหรับผู้ที่ไม่ใช่นักพัฒนาเพราะมันไม่สมมาตร SQL ใช้เป็นครั้งคราวโดยโปรแกรมเมอร์ไม่ที่จะทำให้คำสั่งที่เรียบง่ายและความหมายกึ่งเปิดจะได้รับมากมากขึ้นทำให้เกิดความสับสนสำหรับพวกเขา


9
ตัวอย่างของคุณมุ่งเน้นไปที่จำนวนเต็มสำหรับตัวเลขทศนิยมและปริมาณที่มีการคั่นอื่น ๆ (เช่นวันที่) คำระหว่างนั้นไม่ชัดเจน ถ้าฉันบอกว่าคุณได้ทำ X ระหว่าง 2012 และ 2013 ฉันไม่ได้รวม 2013 (หรือเฉพาะวัน 2013-01-01)
Todd

4
@Todd การใช้งานข้อกำหนดเหล่านี้ไม่ชัดเจน นั่นคือเหตุผลที่นักคณิตศาสตร์นักวิทยาศาสตร์และโปรแกรมเมอร์ที่มีความชำนาญจัดทำเอกสารแสดงเจตนาของพวกเขาในฐานะ "เปิดครึ่ง" หรือเช่นนั้น ฉันคิดว่าประเด็นของคำตอบของ Oleski คือ SQL เดิมมีไว้สำหรับผู้ใช้ปลายทางมากกว่าโปรแกรมเมอร์ (จริง ๆ !) เห็นได้ชัดว่านักออกแบบ SQL ใช้คำจำกัดความที่พวกเขาคิดว่าดีที่สุดสำหรับผู้ชมนั้น แต่ตามที่ผู้เขียนคำถามแนะนำครึ่งเปิดจะดีกว่าสำหรับการทำงานกับช่วงเช่นช่วงเวลา
Basil Bourque

"ฉันคิดว่าการรวมระหว่างการใช้งานง่ายขึ้น" เป็นเรื่องส่วนตัว "บางครั้งผู้ใช้ที่ไม่ใช่โปรแกรมเมอร์จะใช้ SQL เพื่อสร้างเคียวรีแบบง่าย" - ผู้ที่ไม่ใช่โปรแกรมเมอร์ก็จำเป็นต้องตรวจสอบสเป็คอย่างเท่าเทียมกัน
ทอดด์


คำถามนี้มักถูกถามว่า "เลือกหมายเลขจาก 1 ถึง 10" (เพื่อหลีกเลี่ยงความกำกวมที่เห็นได้ชัด) ในฐานะที่เป็นบันทึกด้านข้าง คุณพูดว่า "เลือกตัวเลขระหว่าง 1 ถึง 10"; คนส่วนใหญ่อาจไม่เลือก 1 หรือ 10 ได้รับนั่นคือปัญหาจิตวิทยา :)ผู้คนยังคงยอมรับ 1 และ 10 ว่าเป็นตัวเลือกที่ถูกต้อง (แม้จะเป็นความหมายที่ไม่ถูกต้อง) แต่นั่นเป็นผลมาจากการตีความตามบริบทสมมติว่า 1 และ 10 นั้นถูกต้อง ถ้าคุณจะพูดว่า: "ระหว่าง 13 และ 24" และคุณมีแนวโน้มที่จะถูกถามว่ารวม 13 และ 24
ไม่แยแส

25

คำถาม: ทำไมรวม SQL ระหว่าง?

คำตอบ: เนื่องจากนักออกแบบภาษา SQL ได้ทำการตัดสินใจการออกแบบที่ไม่ดีเนื่องจากพวกเขาไม่สามารถส่งไวยากรณ์ที่จะช่วยให้นักพัฒนาสามารถระบุว่าตัวแปร 4 ตัวใดของ BETWEEN (ปิด, กึ่งเปิดซ้าย, กึ่งเปิดขวาหรือเปิด ) พวกเขาต้องการ

คำแนะนำ: นอกจาก / จนกว่าจะมีการแก้ไขมาตรฐาน SQL อย่าใช้ระหว่างวันที่ / เวลา แทนที่จะเป็นนิสัยของการเข้ารหัสช่วงวันที่ DATE เป็นเงื่อนไขที่เป็นอิสระในขอบเขตเริ่มต้นและจุดสิ้นสุดของช่วง BETWEEN ของคุณ นี่เป็นคำอธิบายที่ละเอียด แต่จะทำให้คุณเขียนเงื่อนไขที่เข้าใจง่าย (มีโอกาสน้อยที่จะบั๊กกี้) และชัดเจนกับตัวปรับแต่งฐานข้อมูลเพื่อให้สามารถกำหนดแผนการดำเนินการที่เหมาะสมและใช้ดัชนีได้

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

  • WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1

พยายามเขียนตรรกะโดยใช้ระหว่างความเสี่ยงปัญหาประสิทธิภาพและ / หรือรหัสรถ สามนับครั้งไม่ถ้วนที่พบบ่อย:

1) WHERE DATE_FIELD BETWEEN :dt AND :dt+1

นี่เป็นข้อผิดพลาดเกือบแน่นอน - ผู้ใช้คาดว่าจะเห็นเฉพาะระเบียนสำหรับวันที่ระบุ แต่วันหนึ่งจะสิ้นสุดลงด้วยรายงานที่มีบันทึกจากเวลา 12:00 น. ของวันถัดไป

2) WHERE TRUNC(DATE_FIELD) = :dt

ให้คำตอบที่ถูกต้อง แต่การใช้ฟังก์ชั่นกับ DATE_FIELD จะทำให้การจัดทำดัชนี / สถิติส่วนใหญ่ไร้ประโยชน์ (แม้ว่าบางครั้ง DBA จะพยายามช่วยด้วยการเพิ่มดัชนีตามฟังก์ชั่นในฟิลด์วันที่ - ยังคงเผาผลาญชั่วโมงมนุษย์ การดำเนินงานบนโต๊ะ)

3) WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60

Tom Kyte ผู้ชำนาญพิเศษด้าน Oracle guru แนะนำวิธีการแก้ปัญหาที่ไม่หรูหรา (IMO) นี้ ทำงานได้ดีจนกระทั่งคุณใช้เวลาทั้งวันเพื่อหาคำว่า "1-1 / 24/06/60" ในข้อความค้นหาที่ให้ผลลัพธ์ที่ไม่สมบูรณ์ ... หรือจนกว่าคุณจะใช้มันในฟิลด์ TIMESTAMP โดยไม่ตั้งใจ นอกจากนี้มันเป็นกรรมสิทธิ์เล็กน้อย เข้ากันได้กับประเภทข้อมูล DATE ของออราเคิล (ซึ่งติดตามไปที่สอง) แต่จำเป็นต้องปรับให้เข้ากับความแม่นยำ DATE / TIME ของผลิตภัณฑ์ฐานข้อมูลที่แตกต่างกัน

การแก้ไข: ร้องเรียนคณะกรรมการ ANSI SQL เพื่อปรับปรุงรายละเอียดภาษา SQL โดยการแก้ไขไวยากรณ์ระหว่างเพื่อรองรับคุณสมบัติของทางเลือกอื่น ๆ ที่เป็นค่าเริ่มต้น CLOSED / INCLUSIVE สิ่งนี้จะเป็นการหลอกลวง:

expr1ระหว่าง expr2 [ INCL [USIVE] | EXCL [ใช้งาน]] และexpr3 [ INCL [ใช้งาน] | EXCL [ใช้งาน]]

พิจารณาว่ามันง่ายที่จะแสดงWHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE(หรือเพียงแค่WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL)

อาจจะเป็น ANSI SQL: 2015?


คำตอบนี้เป็นคำแนะนำของปราชญ์
Basil Bourque

@KevinKirkPatrick - คำตอบยอดเยี่ยม! ฉันขอแนะนำให้คุณลองค้นหาเอกสารประกอบการตัดสินใจเป็นหลักฐานวัตถุประสงค์ของต้นฉบับดั้งเดิม
ทอดด์

3
ฉันชอบexp1 BETWEEN exp2 AND exp3 AND exp1 != exp3วิธีที่คุณได้รับเพื่อให้ผู้ปฏิบัติงานระหว่างนั้นเพื่อให้คุณรู้ว่ามันเป็นภาคที่อยู่ในช่วงและภาคที่ไม่เท่าเทียมกันทำให้มั่นใจได้ว่ามันเป็นแบบกึ่งเปิด
Sentinel

@Sentinel, ดีมาก! ฉันจะไม่ประกาศตัวแปลงก่อนกำหนด แต่ฉันจะจำตัวแปรนี้ไว้ในใจเมื่อฉันกำหนดเงื่อนไขช่วงวันที่ถัดไป ที่หน้าแดงแรกจะมีการอุทธรณ์ทางภาษาที่ดีกว่า exp1> = exp2 และ exp1 <exp3; และเห็นได้ชัดว่าแก้ปัญหาด้วยกันระหว่างกัน ฉันสนใจถ้าเครื่องมือเพิ่มประสิทธิภาพใด ๆ แสดง "ความเข้าใจ" ที่ดีกว่าของรูปแบบหนึ่งเหนืออีกรูปแบบหนึ่ง แน่นอนว่าน่าจะเป็นไปได้ว่าคุณอาจให้ผลลัพธ์ที่ดีขึ้นในเรื่องนั้นด้วย (แม้ว่าจะตรงไปตรงมาฉันก็ค่อนข้างผิดหวังในเครื่องมือเพิ่มประสิทธิภาพที่ปฏิบัติต่อพวกเขาแตกต่างกัน)
KevinKirkpatrick

@KevinKirkpatrick ฉันไม่เคยโปรไฟล์พวกเขาเพื่อให้แน่ใจว่ามีความแตกต่างใด ๆ และฉันก็จะผิดหวังเช่นกันหากมี
Sentinel

8

ทั้งแบบมีส่วนร่วม ( a <= x <= b) และแบบพิเศษ ( a < x < b) มีความเหมือนกันโดยทั่วไปดังนั้นเมื่อทำมาตรฐานพวกเขาก็ต้องเลือกอย่างใดอย่างหนึ่ง โดยทั่วไป "ระหว่าง" ในภาษาอังกฤษทั่วไปนั้นรวมอยู่ด้วยและคำสั่ง SQL หมายถึงการอ่านคล้ายกับประโยคภาษาอังกฤษดังนั้นการครอบคลุมจึงเป็นตัวเลือกที่สมเหตุสมผล


4
การใช้ภาษาอังกฤษนั้นมีความหลากหลายมากยิ่งขึ้นเมื่อคุณปล่อย Half-Open ออกไป เมื่อเราพูดว่า "อาหารกลางวันอยู่ระหว่างเที่ยงถึง 13.00 น." เราหมายถึงครึ่งเปิดในที่ที่คุณคาดว่าจะกลับมาในชั้นเรียน / ทำงานในเวลา 13: 00: 00.000 โดยมีการหยุดพักไปถึงแต่ไม่รวมช่วงเวลาแรกของ ชั่วโมงเดียว a <= x < bคือ Half-Open
Basil Bourque

1
@BasilBourque: นี่อาจเป็นเพราะความแม่นยำไม่มีที่สิ้นสุด - เช่นอาหารกลางวันอยู่ระหว่างเที่ยงถึง 12: 59: 99.9999999999999 ....
Brendan

@Brendan ใช่คุณกำลังทำให้จุดของฉัน ความแม่นยำที่ไม่สิ้นสุด (หรือคลุมเครือ) เป็นหนึ่งในปัญหาที่ได้รับการจัดการโดยใช้วิธีการครึ่งเปิดเพื่อกำหนดช่วงเวลา ประเด็นที่นี่คือในการสนทนาภาษาอังกฤษเราจัดการเปิดและปิดอย่างสังหรณ์ใจ (ดังกล่าวในคำตอบนี้) เช่นเดียวกับช่วงเปิดครึ่งโดยไม่คิดมาก แต่ละวิธีมีจุดประสงค์ นั่นคือเหตุผลที่นิยาม SQL ของ BETWEEN น้อยกว่าค่าที่เหมาะสม จะเป็นการดีที่ SQL จะปฏิบัติตามข้อเสนอแนะโดย KevinKirkpatrick
Basil Bourque

2
SQL ควรเป็นภาษาอังกฤษและถึงแม้ว่าจะเป็นแบบรวมและแบบเอกสิทธิ์เฉพาะบุคคลอาจจะเท่ากัน แต่ก็เป็นภาษาคิวรีสำหรับนักวิเคราะห์และโปรแกรมเมอร์ ในฐานะโปรแกรมเมอร์ฉันคิดว่ามันผิด แต่นั่นไม่สำคัญเลยฉันแค่หลีกเลี่ยงการใช้ "ระหว่าง" ไม่ใช่เรื่องใหญ่.
ทอดด์

5

ตัวดำเนินการไม่ได้ถูกเรียก∩[a,b)มันถูกเรียกBETWEENดังนั้นจึงมีความเหมาะสมมากกว่าสำหรับความหมายของมันที่จะเป็นวลีภาษาอังกฤษ "อยู่ระหว่าง" มากกว่าของภาคแสดงทางคณิตศาสตร์ "อยู่ในช่วงกึ่งเปิด"


เราจำเป็นต้องพิจารณาแอปพลิเคชั่นทั้งหมดไม่ใช่แอปพลิเคชั่นภาษาอังกฤษสำหรับชุดเลขจำนวนเต็ม "ระหว่าง 1 ถึง 10", "ระหว่างเที่ยงถึง 13.00 น.", "ระหว่าง 1.0 ถึง 5.0" (กรัม) "ระหว่าง 5.50 ถึง 10.30" (ดอลลาร์) ปริมาณต่อเนื่องจะมีเหตุผล (อังกฤษ) ถือว่าเป็นพิเศษ
ทอดด์

1
ปัญหาคือBETWEENผู้ใช้งานไม่ได้ใช้ความหมายของวลีภาษาอังกฤษว่า "อยู่ระหว่าง" ในภาษาอังกฤษ "ระหว่าง" คือเวลาพื้นที่หรือช่วงเวลาที่แยกสิ่งต่าง ๆ (เช่นมันพิเศษ ) หากคุณพยายามเตะประตูลูกต้องผ่านเสาไปยังคะแนน หากคุณกดโพสต์ไม่ผ่านระหว่างพวกเขา - ไม่มีคะแนนสำหรับคุณ
ไม่แยแส

1
@CraigYoung เป็นคำตอบที่ได้รับการยอมรับแนะนำ (และฉันเห็นด้วย), "ถ้าฉันพูดว่า" เลือกหมายเลขระหว่าง 1 ถึง 10 "ผู้คนส่วนใหญ่จะรวมหมายเลข 1 และ 10 [ในช่วงของคำตอบที่เป็นไปได้]" ในโดเมนอวกาศฉันเห็นด้วยกับคุณ แต่สำหรับตัวเลขฉันบอกว่าต่างกัน ดีกว่าสำหรับภาษาอังกฤษและการใช้งานมากกว่าที่นี่!
AakashM

@AakashM ประเด็นของฉันคือคุณได้อ้างสิทธิ์ในภาษาอังกฤษซึ่งเป็นเท็จโดยการกำหนดคำในพจนานุกรมของคำว่า "ระหว่าง" เพื่อพิสูจน์ความหมายของการเขียนโปรแกรม ความจริงที่ว่ามีความเข้าใจร่วมกันของวลี "ระหว่าง 1 และ 10" มีความเกี่ยวข้องกับความหมายของ "ระหว่าง" และอื่น ๆ ที่เกี่ยวข้องกับตำแหน่ง 1 และ 10 ที่ถืออยู่ในระบบเลขฐานสิบ สมองของมนุษย์ "แก้ไขอัตโนมัติ" ไม่สนใจว่า "ระหว่าง" ยกเว้นจุดสิ้นสุดในกรณีนี้เพราะมันไร้สาระที่จะหมายถึง "ตั้งแต่ 2 ถึง 9" ลองทำเช่นเดียวกันกับ "ระหว่าง 13 และ 24" หรือแม้แต่ "ระหว่าง 0 ถึง 11"
ไม่แยแส

ระหว่างคุณกับฉันการอ้างสิทธิ์แบบแบ่งหมวดหมู่เกี่ยวกับภาษาธรรมชาติมักไม่ปลอดภัย
AakashM
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.