SQL: ANTARA vs <= dan> =

111

Di SQL Server 2000 dan 2005:

  • apa perbedaan antara kedua WHEREklausa ini?
  • mana yang harus saya gunakan pada skenario mana?

Pertanyaan 1:

SELECT EventId, EventName
FROM EventMaster
WHERE EventDate BETWEEN '10/15/2009' AND '10/18/2009'

Pertanyaan 2:

SELECT EventId, EventName
FROM EventMaster
WHERE EventDate >='10/15/2009'
  AND EventDate <='10/18/2009'

(Sunting: Tanggal Peristiwa kedua awalnya hilang, jadi kueri salah secara sintaks)

Shyju
sumber
1
Ini adalah duplikat semu dengan stackoverflow.com/questions/1572840/sql-between-v1-and-v2
mjv
6
tidak juga, penanganan datetime sedikit berbeda, ditambah lagi untuk SQL server 2008, dan tidak mungkin Shyju bisa memastikan tanpa menanyakan bahwa jawabannya akan sama untuk versi sebelumnya.
Irfy

Jawaban:

119

Keduanya identik: BETWEENmerupakan singkatan dari sintaks yang lebih panjang dalam pertanyaan.

Gunakan sintaks yang lebih panjang alternatif di mana BETWEENtidak berfungsi misalnya

Select EventId,EventName from EventMaster
where EventDate >= '10/15/2009' and EventDate < '10/18/2009'

(Perhatikan <daripada <=dalam kondisi kedua.)

Tony Andrews
sumber
19
Mungkin Anda harus menekankan poin bahwa kondisi kedua adalah '<'. Saya butuh waktu lama untuk melihat perbedaannya.
zendar
21
Saya akan menambahkan bahwa saya sangat menyarankan untuk tidak pernah menggunakan ANTARA kecuali Anda berurusan dengan tipe data DATE atau telah menjamin bahwa nilai-nilai datetime Anda tidak akan pernah memiliki komponen waktu. Bersikap konsisten tentang hal ini akan mengurangi kemungkinan Anda menggunakan ANTARA karena kesalahan daripada> = dan <, dan mendapatkan beberapa data dalam kueri yang tidak Anda maksud, atau berpikir bahwa Anda mendapatkan hari tambahan data saat Anda tidak ...
Aaron Bertrand
1
Apakah akan ada langkah kompilator kedua saat ANTARA diubah menjadi kondisional? Saya mengerti ini agak berlebihan tetapi apakah akan ada biaya tambahan?
James Scott
1
@xmashallax karena mereka? Bagaimana tidak?
Tony Andrews
2
Aneh ... Saya rasa saya bingung dengan pertanyaan, penulisan jawaban, komentar dan fakta bahwa kode saya jelas-jelas memiliki bug sekarang =)
xmashallax
37

Mereka sama.

Satu hal yang harus diperhatikan, adalah jika Anda menggunakan ini terhadap DATETIME, pertandingan untuk tanggal akhir akan menjadi permulaan hari:

<= 20/10/2009

tidak sama dengan:

<= 20/10/2009 23:59:59

(itu akan cocok dengan <= 20/10/2009 00:00:00.000)

Irfy
sumber
Anda cukup menggunakan antara '2009-10-20' dan '2009-10-21' untuk mengabadikan hari
David Andrei Ned
4
@DavidAndreiNed yang juga akan cocok dengan '2009-10-21 00: 00: 00.000' - mungkin bukan yang Anda inginkan.
Hans Ke st ing
2
Anda ingin bidang BETWEEN '2009-10-20 00:00:00' AND '2009-10-20 23:59:59' atau bidang> = '2009-10-20 00:00:00' DAN bidang <= '2009-10-20 23:59:59' untuk memastikannya sepenuhnya.
Geilt
@geilt Contoh Anda akan melewatkan apa pun yang terjadi dalam detik terakhir hari itu ... yaitu: di antara 23:59:59 dan 00:00:00 pada hari berikutnya.
Seth Flowers
00:00:00 adalah awal dari hari berikutnya dan mengapa saya menggunakan> = dan <= dan bukan> atau <. Tetapi jika yang Anda maksud adalah mikrodetik dan Anda menyimpannya maka Anda juga ingin memasukkan mikrodetik terakhir dan terakhir.
Geilt
14

Meskipun BETWEENmudah dibaca dan dipelihara, saya jarang merekomendasikan penggunaannya karena ini adalah interval tertutup dan seperti yang disebutkan sebelumnya, ini dapat menjadi masalah dengan tanggal - bahkan tanpa komponen waktu.

Misalnya, ketika berurusan dengan data bulanan, sering kali umum untuk membandingkan tanggal BETWEEN first AND last, tetapi dalam praktiknya biasanya lebih mudah untuk menulis dt >= first AND dt < next-first(yang juga memecahkan masalah paruh waktu) - karena lastbiasanya menentukan satu langkah lebih lama daripada menentukan next-first(dengan mengurangi satu hari) .

Selain itu, gotcha lain adalah bahwa batas bawah dan atas perlu ditentukan dalam urutan yang benar (yaitu BETWEEN low AND high).

Cade Roux
sumber
4

Biasanya, tidak ada perbedaan - BETWEENkata kunci tidak didukung di semua platform RDBMS, tetapi jika ya, kedua kueri tersebut harus identik.

Karena keduanya identik, sebenarnya tidak ada perbedaan dalam hal kecepatan atau hal lainnya - gunakan yang tampak lebih alami bagi Anda.

marc_s
sumber
4

Seperti yang disebutkan oleh @marc_s, @Cloud, et al. mereka pada dasarnya sama untuk jarak tertutup.

Tetapi setiap nilai waktu pecahan dapat menyebabkan masalah dengan kisaran tertutup (besar-atau-sama dan kurang-atau-sama ) sebagai lawan dari berbagai setengah terbuka (lebih-atau-sama dan kurang ) dengan nilai akhir setelah itu saat terakhir mungkin.

Jadi untuk menghindari kueri tersebut harus ditulis ulang sebagai:

SELECT EventId, EventName
  FROM EventMaster
 WHERE (EventDate >= '2009-10-15' AND
        EventDate <  '2009-10-19')    /* <<<== 19th, not 18th */

Karena BETWEENtidak berfungsi untuk interval setengah terbuka, saya selalu memperhatikan setiap tanggal / waktu kueri yang menggunakannya, karena mungkin ini adalah kesalahan.

devstuff
sumber
4

Saya memiliki sedikit preferensi BETWEENkarena membuatnya langsung jelas bagi pembaca bahwa Anda memeriksa satu bidang untuk suatu rentang . Ini terutama benar jika Anda memiliki nama bidang yang serupa di tabel Anda.

Jika, katakanlah, tabel kita memiliki a transactiondatedan a transitiondate, jika saya baca

transactiondate between ...

Saya langsung tahu bahwa kedua ujung ujian berlawanan dengan bidang yang satu ini.

Jika saya membaca

transactiondate>='2009-04-17' and transactiondate<='2009-04-22'

Saya harus mengambil waktu ekstra untuk memastikan kedua bidang tersebut sama.

Selain itu, saat kueri diedit dari waktu ke waktu, programmer yang ceroboh mungkin memisahkan dua bidang. Saya telah melihat banyak pertanyaan yang mengatakan sesuatu seperti

where transactiondate>='2009-04-17'
  and salestype='A'
  and customernumber=customer.idnumber
  and transactiondate<='2009-04-22'

Jika mereka mencoba ini dengan BETWEEN, tentu saja, ini akan menjadi kesalahan sintaks dan segera diperbaiki.

Jay
sumber
3

Saya pikir satu-satunya perbedaan adalah jumlah gula sintaksis pada setiap kueri. BETWEEN hanyalah cara licin untuk mengatakan persis sama dengan kueri kedua.

Mungkin ada beberapa perbedaan spesifik RDBMS yang tidak saya sadari, tetapi menurut saya tidak demikian.

pyrocumulus
sumber
2

Secara logika tidak ada perbedaan sama sekali. Dari segi kinerja, biasanya, pada sebagian besar DBMS- tidak ada perbedaan sama sekali.

mjv
sumber
1

Penafian: Semua yang di bawah ini hanyalah anekdot dan diambil langsung dari pengalaman pribadi saya. Siapa pun yang ingin melakukan analisis yang lebih teliti secara empiris dipersilakan untuk melaksanakannya dan tidak memilih jika saya. Saya juga menyadari bahwa SQL adalah bahasa deklaratif dan Anda tidak harus mempertimbangkan BAGAIMANA kode Anda diproses saat Anda menulisnya, tetapi, karena saya menghargai waktu saya, saya lakukan.

Ada pernyataan ekuivalen logis tak hingga, tapi saya akan mempertimbangkan tiga (ish).

Kasus 1: Dua Perbandingan dalam urutan standar (Urutan evaluasi diperbaiki)

A> = MinBound DAN A <= MaxBound

Kasus 2: Gula sintaksis (Urutan evaluasi tidak dipilih oleh penulis)

ANTARA MinBound DAN MaxBound

Kasus 3: Dua Perbandingan dalam urutan terpelajar (Urutan evaluasi dipilih pada waktu penulisan)

A> = MinBound DAN A <= MaxBound

Atau

A <= MaxBound DAN A> = MinBound

Dalam pengalaman saya, Kasus 1 dan Kasus 2 tidak memiliki perbedaan kinerja yang konsisten atau mencolok karena mereka tidak mengetahui kumpulan data.

Namun, Kasus 3 dapat sangat meningkatkan waktu eksekusi. Secara khusus, jika Anda bekerja dengan kumpulan data yang besar dan kebetulan memiliki pengetahuan heuristik tentang apakah A lebih cenderung lebih besar dari MaxBound atau lebih kecil dari MinBound, Anda dapat meningkatkan waktu eksekusi secara nyata dengan menggunakan Kasus 3 dan mengurutkan perbandingan demikian.

Satu kasus penggunaan yang saya miliki adalah menanyakan kumpulan data historis besar dengan tanggal yang tidak diindeks untuk catatan dalam interval tertentu. Saat menulis kueri, saya akan memiliki gagasan yang baik tentang apakah ada lebih banyak data SEBELUM interval yang ditentukan atau SETELAH interval yang ditentukan dan dapat memesan perbandingan saya sesuai. Saya telah memotong waktu eksekusi hingga setengahnya tergantung pada ukuran kumpulan data, kompleksitas kueri, dan jumlah catatan yang difilter oleh perbandingan pertama.

LanchPad
sumber
Um, apa? Kasus 3 tidak berbagi logika yang sama seperti Kasus 1 dan Kasus 2. Jika Anda ingin melihat apakah Alebih besar dari kedua batas, maka periksa saja apakah Alebih besar dari MaxBound. Pos Anda perlu beberapa penyesuaian.
mickmackusa
Sepertinya saya salah ketik pada operator persamaan. Tangkapan yang bagus.
LanchPad
0

Dalam skenario ini col BETWEEN ... AND ...dan col <= ... and col >= ...setara.


Standar SQL juga mendefinisikan predikat T461 Symmetric BETWEEN :

 <between predicate part 2> ::=
 [ NOT ] BETWEEN [ ASYMMETRIC | SYMMETRIC ]
 <row value predicand> AND <row value predicand>

Transact-SQL tidak mendukung fitur ini.

BETWEENmengharuskan nilai diurutkan. Misalnya:

SELECT 1 WHERE 3 BETWEEN 10 AND 1
-- no rows

<=>

SELECT 1 WHERE 3 >= 10 AND 3 <= 1
-- no rows

Di samping itu:

SELECT 1 WHERE 3 BETWEEN SYMMETRIC 1 AND 10;
-- 1

SELECT 1 WHERE 3 BETWEEN SYMMETRIC 10 AND 1
-- 1

Ini berfungsi persis seperti biasa BETWEENtetapi setelah mengurutkan nilai perbandingan.

db <> demo biola

Lukasz Szozda
sumber