Tại sao SQL GIỮA bao gồm thay vì nửa mở?


45

Các khoảng thời gian nửa mở (hoặc nửa mở, nửa đóng , nửa giới hạn ) ( [a,b), trong đó xthuộc về khoảng iff a <= x < b) khá phổ biến trong lập trình, vì chúng có nhiều thuộc tính thuận tiện.

Bất cứ ai cũng có thể đưa ra một lý do giải thích tại sao SQL BETWEENsử dụng một khoảng đóng ( [a,b])? Đây là đặc biệt. bất tiện cho ngày tháng. Tại sao bạn lại BETWEENcư xử như vậy?


Tôi tò mò, họ có những tính chất tiện lợi nào?
phant0m

2
nếu nó không được bao gồm, làm thế nào bạn có thể dễ dàng truy vấn tất cả các tên trong phạm vi từ A đến D? hoặc tên W đến Z? Đối với các số từ 1 đến 10, bạn có thể tìm kiếm 0 <n <11, nhưng đối với các ký tự bạn sẽ phải sử dụng số ASCII? hoặc số unicode? Thêm vào đó, các chỉ mục có thể dễ dàng đưa bạn đến điểm bắt đầu của dữ liệu của bạn.
JQA

2
Tôi hiểu sự thất vọng của bạn, (StartDate> = '2010-01-01' và StartDate <'2011-01-01'), hoạt động rất hay, để sử dụng Giữa các điểm tương đương sẽ là (StartDate giữa '2010-01-01' và ' 2010-12-31 23:59:59 '), cả cồng kềnh và người ta cần biết có bao nhiêu ngày trong tháng 12
Todd

1
@ phant0m [a, b) U [c, d) == [a, d). [a: int, b: int) chứa chính xác ba phần tử. Nhận xét của Todd cho thấy cách họ làm việc đặc biệt tốt cho các ngày (mà tôi nhớ họ nhất). Về cơ bản, khi mã hóa, các khoảng thời gian semiopen có xu hướng đơn giản hơn, dễ sử dụng và mạnh mẽ hơn.
alex

Câu trả lời tốt nhất nên được tham chiếu tài liệu quyết định khách quan từ những người đầu tiên chỉ định GIỮA cho SQL, qua đó trả lời Tại sao, thay vì câu trả lời chủ quan được chọn.
Todd

Câu trả lời:


48

Tôi nghĩ rằng bao gồm BETWEENlà trực quan hơn (và rõ ràng, các nhà thiết kế SQL cũng vậy) hơn là một khoảng thời gian bán mở. Ví dụ: nếu tôi nói "Chọn một số trong khoảng từ 1 đến 10", hầu hết mọi người sẽ bao gồm các số 1 và 10. Khoảng thời gian kết thúc mở thực sự đặc biệt khó hiểu đối với những người không phải là nhà phát triển vì nó không đối xứng. SQL là thỉnh thoảng được sử dụng bởi các lập trình để thực hiện các truy vấn đơn giản, và ngữ nghĩa bán mở sẽ có được nhiều hơn khó hiểu cho họ.


9
Ví dụ của bạn tập trung vào số nguyên, cho các số thập phân và các đại lượng được phân tách khác (chẳng hạn như ngày), thuật ngữ giữa là không rõ ràng. Nếu tôi nói bạn đã thực hiện X trong khoảng thời gian từ 2012 đến 2013, thì tôi không bao gồm 2013 (hoặc cụ thể là ngày 2013-01-01)
Todd

4
@Todd Bất kỳ việc sử dụng các thuật ngữ này là mơ hồ. Đó là lý do tại sao các nhà toán học, nhà khoa học và lập trình viên hiểu biết ghi lại ý định của họ là "nửa mở" hoặc đại loại như vậy. Tôi nghĩ rằng câu trả lời của Oleski là SQL ban đầu được dành cho người dùng cuối chứ không phải lập trình viên (thực sự!). Rõ ràng các nhà thiết kế SQL đã đâm vào một định nghĩa mà họ nghĩ là tốt nhất cho đối tượng đó. Nhưng như các tác giả của Câu hỏi gợi ý, nửa mở hầu như luôn luôn tốt hơn để làm việc với các phạm vi như khoảng thời gian.
Basil Bourque

"Tôi nghĩ rằng bao gồm GIỮA là trực quan hơn" là chủ quan. "SQL đôi khi được sử dụng bởi những người không lập trình để thực hiện các truy vấn đơn giản" - Những người không lập trình cũng cần phải kiểm tra thông số kỹ thuật.
Todd


Câu hỏi cũng thường được hỏi "Chọn một số từ 1 đến 10" (đơn giản là để tránh sự mơ hồ rõ ràng). Như một lưu ý phụ. Bạn nói "chọn một số trong khoảng từ 1 đến 10"; hầu hết mọi người có thể sẽ không chọn 1 hoặc 10. Được cho rằng đó là vấn đề tâm lý nhiều hơn. :) Mọi người vẫn sẽ chấp nhận 1 và 10 là các lựa chọn hợp lệ (mặc dù không đúng về mặt ngữ nghĩa); nhưng đó là kết quả của việc giải thích theo ngữ cảnh giả sử 1 và 10 là hợp lệ. Nếu bạn định nói: "từ 13 đến 24" và bạn có nhiều khả năng được hỏi liệu có bao gồm 13 và 24 không.
vỡ mộng

26

HỎI: Tại sao SQL bao gồm GIỮA?

TRẢ LỜI: Bởi vì các nhà thiết kế ngôn ngữ SQL đã đưa ra một quyết định thiết kế kém, trong đó họ không cung cấp cú pháp cho phép các nhà phát triển chỉ định biến thể nào trong 4 biến thể của GIỮA (đóng, bán mở trái, bán phải hoặc mở ) họ muốn.

KIẾN NGHỊ: Trừ khi / cho đến khi tiêu chuẩn SQL được sửa đổi, không sử dụng GIỮA cho ngày / lần. Thay vào đó, hãy tập thói quen mã hóa so sánh phạm vi DATE dưới dạng các điều kiện độc lập trên ranh giới bắt đầu và kết thúc của phạm vi GIỮA của bạn. Đây là một chút dài dòng, nhưng sẽ để lại cho bạn các điều kiện viết trực quan (do đó ít có lỗi hơn) và rõ ràng với các trình tối ưu hóa cơ sở dữ liệu, cho phép xác định các kế hoạch thực hiện tối ưu và sử dụng các chỉ mục.

Ví dụ: nếu truy vấn của bạn chấp nhận thông số kỹ thuật của ngày đầu vào và sẽ trả về tất cả các bản ghi rơi vào ngày đó, bạn sẽ mã là:

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

Cố gắng viết logic bằng cách sử dụng GIỮA rủi ro về các vấn đề về hiệu năng và / hoặc mã lỗi. Ba sai lầm phổ biến:

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

Đây gần như chắc chắn là một lỗi - người dùng hy vọng sẽ chỉ thấy các bản ghi cho một ngày cụ thể, nhưng một ngày nào đó sẽ xuất hiện với một báo cáo có chứa các bản ghi từ 12:00 sáng ngày hôm sau.

2) WHERE TRUNC(DATE_FIELD) = :dt

Đưa ra câu trả lời đúng, nhưng áp dụng chức năng cho DATE_FIELD sẽ khiến hầu hết việc lập chỉ mục / thống kê trở nên vô dụng (mặc dù đôi khi các DBA sẽ cố gắng giúp bằng cách thêm các chỉ mục dựa trên chức năng vào các trường ngày - vẫn đốt cháy thời gian của con người và không gian đĩa và thêm chi phí vào IUD thao tác trên bàn)

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

Tom Kyte, Oracle gord Extraordinaire, đề xuất giải pháp ít thanh lịch (IMO) này. Hoạt động tuyệt vời cho đến khi bạn dành cả ngày để thấy rằng "1-1 / 24/06/60" trong truy vấn mang lại kết quả không đầy đủ ... hoặc cho đến khi bạn vô tình sử dụng nó trên trường TIMESTAMP. Thêm vào đó, nó là một chút độc quyền; tương thích với kiểu dữ liệu DATE của Oracle (theo dõi thứ hai), nhưng cần được điều chỉnh theo độ chính xác DATE / TIME của các sản phẩm cơ sở dữ liệu khác nhau.

GIẢI PHÁP: Yêu cầu ủy ban SQL ANSI tăng cường các đặc tả ngôn ngữ SQL bằng cách sửa đổi cú pháp GIỮA để hỗ trợ đặc tả các lựa chọn thay thế cho mặc định ĐÓNG / INCLUSIVE. Một cái gì đó như thế này sẽ thực hiện các mẹo:

expr1 GIỮA expr2 [ INCL [USIVE] | EXCL [USIVE]] VÀ expr3 [ INCL [USIVE] | EXCL [USIVE]]

Xem xét cách dễ dàng để thể hiện WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE(hoặc chỉ WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL)

Có lẽ ANSI SQL: 2015?


Câu trả lời này là lời khuyên hiền.
Basil Bourque

@KevinKirkPatrick - Câu trả lời tuyệt vời! Tôi đề nghị bạn cũng cố gắng tìm tài liệu quyết định làm bằng chứng khách quan của bản gốc Tại sao.
Todd

3
Cá nhân tôi thích exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3cách bạn giữ được toán tử giữa các toán tử để bạn biết đó là một vị từ có phạm vi và vị từ bất đẳng thức đảm bảo rằng nó được mở.
Sentinel

@Sentinel, hay đấy! Tôi sẽ không tuyên bố bản thân là một chuyển đổi sớm, nhưng tôi chắc chắn sẽ ghi nhớ biến thể này khi tôi mã hóa các điều kiện phạm vi ngày tiếp theo. Ở lần đầu tiên, nó có sức hấp dẫn ngôn ngữ lớn hơn exp1> = exp2 AND exp1 <exp3; và rõ ràng giải quyết các vấn đề với GIỮA tốt như nhau. Tôi sẽ quan tâm nếu bất kỳ trình tối ưu hóa nào cho thấy "sự hiểu biết" lớn hơn về một biến thể so với biến thể khác; chắc chắn, có vẻ hợp lý là bạn cũng có thể mang lại kết quả tốt hơn về vấn đề đó (mặc dù thật lòng mà nói, tôi khá thất vọng về trình tối ưu hóa đã đối xử với họ khác nhau)
KevinKirkpatrick

@KevinKirkpatrick Tôi chưa bao giờ định hình họ để xác định xem có sự khác biệt nào không, và tôi cũng sẽ thất vọng nếu có.
Sentinel

8

Cả inclusive ( a <= x <= b) và Exclusive ( a < x < b) đều phổ biến như nhau, vì vậy khi đưa ra các tiêu chuẩn, họ chỉ cần chọn một. "Giữa" trong tiếng Anh thông thường thường được bao gồm và một câu lệnh SQL có nghĩa là đọc tương tự như một câu tiếng Anh, vì vậy, bao gồm là một lựa chọn hợp lý.


4
Trên thực tế, việc sử dụng bằng tiếng Anh thậm chí còn hỗn tạp hơn khi bạn bỏ qua Half-Open. Khi chúng tôi nói "bữa trưa là giữa trưa và 1 giờ chiều", chúng tôi có nghĩa là nửa mở trong đó bạn dự kiến ​​sẽ quay lại lớp học / công việc vào lúc 13: 00: 00.000, với thời gian nghỉ giải lao nhưng không bao gồm khoảnh khắc đầu tiên của giờ một giờ. a <= x < blà một nửa mở.
Basil Bourque

1
@BasilBourque: Điều này có thể là do độ chính xác vô hạn - ví dụ: bữa trưa là giữa trưa và 12: 59: 99.9999999999999 ....
Brendan

@Brendan Vâng, bạn đang đưa ra quan điểm của tôi. Độ chính xác vô hạn (hoặc mơ hồ) là một trong những vấn đề được xử lý bằng cách sử dụng phương pháp nửa mở để xác định khoảng thời gian. Vấn đề ở đây là trong cuộc trò chuyện bằng tiếng Anh, chúng tôi trực giác xử lý mở và đóng (như đã đề cập trong câu trả lời này) cũng như các phạm vi nửa mở mà không cần suy nghĩ nhiều. Mỗi cách tiếp cận phục vụ một mục đích. Đó là lý do tại sao định nghĩa SQL của GIỮA là ít hơn tối ưu. Lý tưởng nhất, SQL sẽ làm theo đề xuất của KevinKirkpatrick .
Basil Bourque

2
SQL được coi là giống như tiếng Anh và mặc dù bao gồm và độc quyền có thể phổ biến như nhau, đó là ngôn ngữ truy vấn dành cho các nhà phân tích và lập trình viên. Là một lập trình viên, tôi nghĩ nó được định nghĩa sai, nhưng điều đó không thực sự quan trọng, tôi chỉ tránh sử dụng "GIỮA". Không phải là một thỏa thuận lớn.
Todd

5

Toán tử không được gọi ∩[a,b), nó được gọi BETWEEN, do đó, ngữ nghĩa của nó phù hợp hơn đáng kể với cụm từ tiếng Anh "nằm giữa" so với các vị từ toán học "nằm trong khoảng bán mở".


Người ta cần xem xét tất cả các ứng dụng, không chỉ các ứng dụng tiếng Anh cho các bộ Integer. "Từ 1 đến 10", "giữa trưa và 1 giờ chiều", "giữa 1.0 và 5.0" (gram). "Trong khoảng từ 5,50 đến 10,30" (đô la). Số lượng liên tục sẽ được hợp lý (tiếng Anh) được coi là độc quyền.
Todd

1
Vấn đề là BETWEENnhà điều hành không sử dụng ngữ nghĩa của cụm từ tiếng Anh "nằm giữa". Trong tiếng Anh "giữa" là thời gian, không gian hoặc khoảng cách ngăn cách mọi thứ (nghĩa là độc quyền ). Nếu bạn cố gắng đá một mục tiêu, bóng phải đi giữa các bài để ghi bàn. Nếu bạn nhấn bài không vượt qua được giữa họ - không có điểm nào cho bạn.
vỡ mộng vào

1
@CraigYoung như câu trả lời được chấp nhận cho thấy (và tôi đồng ý), "nếu tôi nói" Chọn một số trong khoảng từ 1 đến 10 ", hầu hết mọi người sẽ bao gồm các số 1 và 10 [trong phạm vi câu trả lời có thể của họ]". Trong một lĩnh vực không gian tôi đồng ý với bạn, nhưng đối với những con số tôi nói nó khác. Mặc dù tốt hơn cho ngôn ngữ và sử dụng tiếng Anh hơn ở đây!
AakashM

@AakashM Quan điểm của tôi là bạn đã đưa ra yêu cầu về ngôn ngữ tiếng Anh, điều này đơn giản là sai theo định nghĩa từ điển của từ "giữa", để biện minh cho ngữ nghĩa lập trình. Thực tế là có một sự hiểu biết chung về cụm từ "giữa 1 và 10" ít liên quan đến ý nghĩa của "giữa" và nhiều hơn với các vị trí 1 và 10 giữ trong hệ thống số thập phân. "Tự động sửa lỗi" của bộ não con người bỏ qua "giữa" loại trừ các điểm kết thúc trong trường hợp này bởi vì nó có vẻ vô lý khi có nghĩa là "từ 2 đến 9". Hãy thử tương tự với "từ 13 đến 24". Hoặc thậm chí "trong khoảng từ 0 đến 11".
vỡ mộng

Giữa bạn và tôi, những tuyên bố phân loại về ngôn ngữ tự nhiên thường không an toàn.
AakashM
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.