So sánh ngày trong Oracle SQL


141

Tôi đang cố gắng để nó hiển thị số lượng nhân viên được thuê sau ngày 20 tháng 6 năm 1994, nhưng tôi gặp lỗi khi nói "số nhận dạng không hợp lệ của JUN. Xin vui lòng giúp đỡ, cảm ơn!

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

1
Cũng lưu ý rằng bạn có thể sử dụng > <hoặcBETWEEN '' AND ''
Andrew

Câu trả lời:


296

31-DEC-95không phải là một chuỗi, cũng không phải là 20-JUN-94. Chúng là những con số có thêm một số thứ được thêm vào cuối. Điều này nên '31-DEC-95'hoặc '20-JUN-94'- lưu ý trích dẫn duy nhất , '. Điều này sẽ cho phép bạn thực hiện một so sánh chuỗi.

Tuy nhiên, bạn không thực hiện so sánh chuỗi; bạn đang làm một so sánh ngày . Bạn nên chuyển đổi chuỗi của bạn thành một ngày. Hoặc bằng cách sử dụng TO_DATE()chức năng tích hợp, hoặc một ngày theo nghĩa đen .

TO_DATE ()

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

Phương pháp này có một vài cạm bẫy không cần thiết

  • Như a_horse_with_no_name đã ghi chú trong các bình luận, DECkhông nhất thiết có nghĩa là tháng 12. Nó phụ thuộc vào NLS_DATE_LANGUAGENLS_DATE_FORMATcài đặt của bạn . Để đảm bảo rằng so sánh của bạn với công việc ở bất kỳ miền địa phương nào, bạn có thể sử dụng mô hình định dạng datetime MM thay thế
  • Năm '95 không chính xác. Bạn biết bạn có nghĩa là năm 1995, nhưng nếu đó là '50, thì đó là năm 1950 hay 2050? Luôn luôn tốt nhất để được rõ ràng
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

Ngày tháng chữ

Một chữ theo ngày là một phần của tiêu chuẩn ANSI, có nghĩa là bạn không phải sử dụng một chức năng cụ thể của Oracle. Khi sử dụng nghĩa đen, bạn phải chỉ định ngày của mình ở định dạng YYYY-MM-DDvà bạn không thể bao gồm yếu tố thời gian.

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

Hãy nhớ rằng kiểu dữ liệu ngày của Oracle bao gồm việc sắp xếp thời gian, vì vậy ngày không có phần thời gian tương đương với 1995-12-31 00:00:00.

Nếu bạn muốn bao gồm một phần thời gian thì bạn phải sử dụng một dấu thời gian bằng chữ, có định dạng YYYY-MM-DD HH24:MI:SS[.FF0-9]

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

Thêm thông tin

NLS_DATE_LANGUAGEcó nguồn gốc từ NLS_LANGUAGENLS_DATE_FORMATcó nguồn gốc từ NLS_TERRITORY. Chúng được đặt khi ban đầu bạn tạo cơ sở dữ liệu nhưng chúng có thể được thay đổi bằng cách thay đổi tệp tham số inialization của bạn - chỉ khi thực sự cần thiết - hoặc ở cấp phiên bằng cách sử dụng ALTER SESSIONcú pháp. Ví dụ:

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

Điều này có nghĩa là:

  • DD ngày số trong tháng, 1 - 31
  • MM tháng số trong năm, 01 - 12 (tháng 1 là 01)
  • YYYYNăm 4 chữ số - theo tôi, điều này luôn tốt hơn năm 2 chữ số YYvì không có sự nhầm lẫn với thế kỷ mà bạn đang đề cập đến.
  • HH24 giờ trong ngày, 0 - 23
  • MI phút của giờ, 0 - 59
  • SS giây thứ hai, 0-59

Bạn có thể tìm ra ngôn ngữ hiện tại và cài đặt ngôn ngữ ngày bằng cách truy vấn V$NLS_PARAMETERSsvà toàn bộ gam giá trị hợp lệ bằng cách truy vấn V$NLS_VALID_VALUES.

đọc thêm


Ngẫu nhiên, nếu bạn muốn nhóm count(*)bạn cần nhómemployee_id

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

Điều này cung cấp cho bạn số lượng mỗi employee_id .


13
+1 để sử dụng mặt nạ định dạng trong to_date (). Lưu ý rằng điều này vẫn có thể thất bại trên các môi trường khác nhau do cài đặt ngôn ngữ khác nhau. DECkhông nhất thiết luôn luôn là một tháng hợp lệ. Thông thường tốt hơn là sử dụng số thay vì tên
a_horse_with_no_name

1
Bạn có thể chỉ định thời gian bằng chữ ANSI - bạn chỉ cần chỉ định một timestampchữ thay vì bằng datechữ: timestamp '2015-01-30 19:42:04' (vì trong ANSI SQL, datekiểu dữ liệu không có thời gian, chỉ có timestampkiểu dữ liệu mới có).
a_horse_with_no_name

1
Các ký tự ngày ANSI thực sự là một cách ngắn gọn so sánh việc phải nhập TO_DATE và Định dạng ngày mỗi lần. Tốt cho các nhà phát triển LAZY như tôi. Một điều cần chú ý là DATE 2016-04-01phương tiện 2016-04-01 00:00:00thực sự. Và tôi nghĩ cú pháp này hoạt động kể từ Oracle 9i vì đây là nơi cú pháp ANSI-SQL được đưa vào Oracle.
LeOn - Han Li

1
Suy nghĩ của tôi đã phát triển đáng kể trong 4 năm qua @Leon :-) 'Tôi đã cập nhật câu trả lời. Tôi đã đề cập rằng một ngày theo nghĩa đen không bao gồm yếu tố thời gian nhưng tôi đã gọi nó rõ ràng hơn như bạn đã nêu. Hỗ trợ mở rộng 9i đã kết thúc gần 6 năm trước ... và đã được phát hành 14 năm trước. Nó không còn phù hợp nữa đối với đại đa số người dùng.
Ben


6

Phần kết luận,

to_char hoạt động theo cách riêng của nó

Vì thế,

Luôn sử dụng định dạng này YYYY-MM-DD để so sánh thay vì MM-DD-YY hoặc DD-MM-YYYY hoặc bất kỳ định dạng nào khác


4

Bạn có thể sử dụng trunc và to_date như sau:

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;

2

từ truy vấn của bạn:

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

Tôi nghĩ rằng nó không hiển thị số lượng nhân viên được thuê sau ngày 20 tháng 6 năm 1994. nếu bạn muốn hiển thị số lượng nhân viên, bạn có thể sử dụng:

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

Tôi nghĩ rằng để thực hành tốt nhất để so sánh ngày bạn có thể sử dụng:

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

-4

Trích dẫn duy nhất phải ở đó, kể từ ngày chuyển đổi thành ký tự.

Chọn worker_id, đếm (*)
Từ nhân viên
Trong đó to_char (worker_date_hired, 'DD-MON-YY')> '31 -DEC-95 ';

1
SQL này sử dụng một định dạng ngày ẩn, nó sẽ không luôn luôn hoạt động.
Jon Heller

5
Nó chỉ hoạt động tốt cho các cài đặt NLS_ * cụ thể của bạn, nó có thể không hoạt động trên các máy khách hoặc máy chủ khác. Câu trả lời được chấp nhận giải thích tại sao một định dạng ngày rõ ràng là quan trọng.
Jon Heller

Phương pháp này là so sánh các chuỗi, không phải ngày. Chuỗi thứ hai bắt đầu bằng "3", do đó, phép so sánh hoạt động như "thứ tự chữ cái". Thật thú vị, loại so sánh này thực sự hoạt động (sắp xếp một cách tình cờ) nếu bạn sử dụng một định dạng như YYYY-MM-DD. Nhưng tất nhiên, tốt hơn là so sánh ngày với ngày ...
Nick Perkins
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.