Membandingkan Tanggal di Oracle SQL

141

Saya mencoba membuatnya menampilkan jumlah karyawan yang dipekerjakan setelah 20 Juni 1994, Tapi saya mendapatkan kesalahan mengatakan "pengidentifikasi tidak valid JUN. Tolong bantu, terima kasih!

Select employee_id, count(*)
From Employee
Where to_char(employee_date_hired, 'DD-MON-YY') > 31-DEC-95; 
pengguna1336830
sumber
1
Perhatikan juga bahwa Anda dapat menggunakan > <atauBETWEEN '' AND ''
Andrew

Jawaban:

296

31-DEC-95bukan string, juga bukan 20-JUN-94. Mereka angka dengan beberapa hal tambahan yang ditambahkan pada akhirnya. Ini harus '31-DEC-95'atau '20-JUN-94'- perhatikan kutipan tunggal,' ,. Ini akan memungkinkan Anda untuk melakukan perbandingan string.

Namun, Anda tidak melakukan perbandingan string; Anda sedang melakukan perbandingan tanggal . Anda harus mengubah string Anda menjadi tanggal. Baik dengan menggunakan TO_DATE()fungsi bawaan, atau literal tanggal .

SAAT INI()

select employee_id
  from employee
 where employee_date_hired > to_date('31-DEC-95','DD-MON-YY')

Metode ini memiliki beberapa jebakan yang tidak perlu

  • Seperti a_horse_with_no_name dicatat dalam komentar,, DECtidak harus berarti Desember. Itu tergantung pada pengaturan NLS_DATE_LANGUAGEdan Anda NLS_DATE_FORMAT. Untuk memastikan bahwa perbandingan Anda dengan pekerjaan di lokal saja Anda dapat menggunakan format model datetime MM bukan
  • Tahun '95 tidak tepat. Anda tahu maksud Anda tahun 1995, tetapi bagaimana jika itu tahun '50, apakah itu tahun 1950 atau 2050? Itu selalu terbaik untuk menjadi eksplisit
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

Literal tanggal

Literal tanggal adalah bagian dari standar ANSI, yang berarti Anda tidak harus menggunakan fungsi spesifik Oracle. Saat menggunakan literal Anda harus menentukan tanggal Anda dalam format YYYY-MM-DDdan Anda tidak dapat memasukkan elemen waktu.

select employee_id
  from employee
 where employee_date_hired > date '1995-12-31'

Ingat bahwa datatype tanggal Oracle menyertakan elemement waktu, sehingga tanggal tanpa porsi waktu sama dengan 1995-12-31 00:00:00 .

Jika Anda ingin memasukkan bagian waktu maka Anda harus menggunakan timestamp literal, yang mengambil format YYYY-MM-DD HH24:MI:SS[.FF0-9]

select employee_id
  from employee
 where employee_date_hired > timestamp '1995-12-31 12:31:02'

Informasi lebih lanjut

NLS_DATE_LANGUAGEberasal dari NLS_LANGUAGEdan NLS_DATE_FORMATberasal dari NLS_TERRITORY. Ini diatur ketika Anda awalnya membuat database tetapi mereka dapat diubah dengan mengubah file parameter inisialisasi Anda - hanya jika benar-benar diperlukan - atau pada tingkat sesi dengan menggunakan ALTER SESSIONsintaks. Misalnya:

alter session set nls_date_format = 'DD.MM.YYYY HH24:MI:SS';

Ini berarti:

  • DD hari numerik bulan itu, 1 - 31
  • MM bulan numerik tahun ini, 01 - 12 (Januari adalah 01)
  • YYYY4 digit tahun - menurut saya ini selalu lebih baik dari tahun 2 digit YYkarena tidak ada kebingungan dengan abad apa yang Anda maksud.
  • HH24 jam sehari, 0-23
  • MI menit, 0 - 59
  • SS menit kedua, 0-59

Anda dapat mengetahui pengaturan bahasa tanggal dan bahasa saat ini dengan kueri V$NLS_PARAMETERSsdan keseluruhan penuh nilai yang valid dengan kueri V$NLS_VALID_VALUES.

Bacaan lebih lanjut


Kebetulan, jika Anda ingin, count(*)Anda perlu mengelompokkan berdasarkanemployee_id

select employee_id, count(*)
  from employee
 where employee_date_hired > date '1995-12-31'
 group by employee_id

Ini memberi Anda hitungan per employee_id .

Ben
sumber
13
+1 untuk menggunakan format mask di to_date (). Perhatikan bahwa ini masih dapat gagal pada lingkungan yang berbeda karena pengaturan bahasa yang berbeda. DECtidak selalu selalu bulan yang valid. Biasanya lebih baik menggunakan angka daripada nama
a_horse_with_no_name
1
Anda dapat menentukan waktu dengan literal ANSI - Anda hanya perlu menentukan timestampliteral alih-alih dateliteral: timestamp '2015-01-30 19:42:04' (karena dalam ANSI SQL datetipe data tidak punya waktu, hanya timestamptipe data yang melakukannya).
a_horse_with_no_name
1
Literal tanggal ANSI benar-benar cara ringkas membandingkan harus mengetik TO_DATE dan Format Tanggal setiap waktu. Bagus untuk pengembang LAZY seperti saya. Satu hal yang Harus Diperhatikan adalah DATE 2016-04-01sarana yang 2016-04-01 00:00:00sesungguhnya. Dan saya pikir sintaks ini bekerja sejak Oracle 9i karena di sinilah sintaks ANSI-SQL diperkenalkan ke Oracle.
LeOn - Han Li
1
Pemikiran saya telah berkembang secara signifikan dalam 4 tahun terakhir @Leon :-) 'Saya telah memperbarui jawabannya. Saya telah menyebutkan bahwa sebuah tanggal literal tidak memasukkan elemen waktu tetapi saya telah menyebutkannya secara lebih eksplisit seperti yang telah Anda nyatakan. Dukungan diperpanjang 9i berakhir hampir 6 tahun yang lalu ... dan dirilis 14 tahun yang lalu. Seharusnya tidak relevan lagi untuk sebagian besar pengguna.
Ben
6

Kesimpulan,

to_char bekerja dengan caranya sendiri

Begitu,

Selalu gunakan format ini YYYY-MM-DD untuk perbandingan, bukan MM-DD-YY atau DD-MM-YYYY atau format lainnya

akshay gulawane
sumber
4

Anda dapat menggunakan trunc dan to_date sebagai berikut:

select TO_CHAR (g.FECHA, 'DD-MM-YYYY HH24:MI:SS') fecha_salida, g.NUMERO_GUIA, g.BOD_ORIGEN, g.TIPO_GUIA, dg.DOC_NUMERO, dg.* 
from ils_det_guia dg, ils_guia g
where dg.NUMERO_GUIA = g.NUMERO_GUIA and dg.TIPO_GUIA = g.TIPO_GUIA and dg.BOD_ORIGEN = g.BOD_ORIGEN
and dg.LAB_CODIGO = 56 
and trunc(g.FECHA) > to_date('01/02/15','DD/MM/YY')
order by g.FECHA;
Giovanny Farto M.
sumber
2

dari kueri Anda:

Select employee_id, count(*) From Employee 
Where to_char(employee_date_hired, 'DD-MON-YY') > '31-DEC-95' 

Saya pikir itu tidak untuk menampilkan jumlah karyawan yang dipekerjakan setelah 20 Juni 1994. jika Anda ingin menunjukkan jumlah karyawan, Anda dapat menggunakan:

Select count(*) From Employee 
Where to_char(employee_date_hired, 'YYYMMMDDD') > 19940620 

Saya pikir praktik terbaik untuk membandingkan tanggal yang dapat Anda gunakan:

employee_date_hired > TO_DATE('20-06-1994', 'DD-MM-YYYY');
or
to_char(employee_date_hired, 'YYYMMMDDD') > 19940620;
viduka
sumber
-4

Kutipan tunggal harus ada di sana, sejak tanggal dikonversi ke karakter.

Pilih employee_id, hitung (*)
Dari Karyawan
Di mana to_char (employee_date_hired, 'DD-MON-YY')> '31 -DEC-95 ';
MVB
sumber
1
SQL ini menggunakan format tanggal implisit, tidak akan selalu berfungsi.
Jon Heller
5
Ini hanya berfungsi dengan baik untuk pengaturan NLS_ * spesifik Anda, mungkin tidak berfungsi pada klien atau server lain. Jawaban yang diterima menjelaskan mengapa format tanggal eksplisit itu penting.
Jon Heller
Metode ini membandingkan string, bukan tanggal. String kedua dimulai dengan "3", jadi pembandingannya bekerja seperti "urutan abjad". Menariknya, jenis perbandingan ini benar-benar berfungsi (semacam kebetulan) jika Anda menggunakan format seperti YYYY-MM-DD. Tapi tentu saja, lebih baik membandingkan tanggal dengan tanggal ...
Nick Perkins