Порівняння дат в Oracle SQL


141

Я намагаюся дозволити йому відобразити кількість працівників, яких прийнято на роботу після 20 червня 1994 р. Але я отримую помилку із зазначенням недійсного ідентифікатора "JUN". Будь ласка, допоможіть, дякую!

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

1
Зауважте також, що ви можете використовувати > <абоBETWEEN '' AND ''
Андрій,

Відповіді:


296

31-DEC-95не є рядком, і не є 20-JUN-94. Вони номери з деякими додатковими матеріалами, доданими в кінці. Це повинно бути '31-DEC-95'або '20-JUN-94'- зверніть увагу на апостроф, '. Це дозволить вам порівняти рядки.

Однак ти не робиш порівняння рядків; ви робите порівняння побачень . Ви повинні перетворити рядок у дату. Або за допомогою вбудованої TO_DATE()функції або літералу дати .

TO_DATE ()

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

Цей метод має кілька непотрібних підводних каменів

  • Як зазначається в коментарях a_horse_with_no_name DEC, не обов'язково означає грудень. Це залежить від ваших NLS_DATE_LANGUAGEта NLS_DATE_FORMATналаштувань. Щоб порівняти роботу з роботою в будь-якій місцевості, замість цього ви можете використовувати модель формату дати MM
  • Рік '95 - неточний. Ви знаєте, ви маєте на увазі 1995 рік, але що, якщо це було 50 років, це 1950 чи 2050 роки? Завжди краще бути явним
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

Літерали дати

Літерал дати є частиною стандарту ANSI, а це означає, що вам не потрібно використовувати специфічну функцію Oracle. Під час використання літералу ви повинні вказати дату у форматі, YYYY-MM-DDі ви не можете включити елемент часу.

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

Пам'ятайте, що тип даних дати Oracle включає часовий елемент, тому дата без часової частини еквівалентна 1995-12-31 00:00:00.

Якщо ви хочете включити часовий проміжок, тоді вам доведеться використовувати літерал часової позначки, який приймає формат YYYY-MM-DD HH24:MI:SS[.FF0-9]

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

Додаткова інформація

NLS_DATE_LANGUAGEпоходить від NLS_LANGUAGEі NLS_DATE_FORMATпоходить від NLS_TERRITORY. Вони встановлюються, коли ви спочатку створили базу даних, але їх можна змінити, змінивши файл параметрів ініалізації - лише якщо це дійсно потрібно - або на рівні сеансу за допомогою ALTER SESSIONсинтаксису. Наприклад:

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

Це означає:

  • DD числовий день місяця, 1 - 31
  • MM числовий місяць року, 01 - 12 (січень - 01)
  • YYYYЧотиризначний рік - на мою думку, це завжди краще, ніж двозначний рік, YYоскільки немає плутанини з тим, до якого століття ви звертаєтесь.
  • HH24 година дня, 0 - 23
  • MI хвилина години, 0 - 59
  • SS секунди хвилини, 0-59

Ви можете дізнатися свої поточні налаштування мови та дати за допомогою запиту V$NLS_PARAMETERSsта повну гаму дійсних значень шляхом запиту V$NLS_VALID_VALUES.

Подальше читання


До речі, якщо ви хочете, count(*)вам потрібно згрупуватисяemployee_id

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

Це дає вам підрахунок на employee_id .


13
+1 для використання маски формату в to_date (). Зауважте, що це може все-таки вийти з ладу в різних середовищах через різні мовні налаштування. DECне обов'язково завжди є дійсним місяцем. Зазвичай краще використовувати номери замість імен
a_horse_with_no_name

1
Ви можете вказати час з літералом ANSI - вам просто потрібно вказати timestampлітерал замість dateлітералу: timestamp '2015-01-30 19:42:04' (оскільки в ANSI SQL dateтип даних не має часу, а лише timestampтип даних).
a_horse_with_no_name

1
Літерали дати ANSI - це дійсно стислий спосіб порівняння необхідності введення TO_DATE та Format Date кожного разу. Добре для ледачих розробників , як я. Одне, що слід помітити, - це DATE 2016-04-01засоби 2016-04-01 00:00:00насправді. І я думаю, що цей синтаксис працює з Oracle 9i, оскільки саме тут синтаксис ANSI-SQL був введений в Oracle.
LeOn - Хан Лі

1
Моє мислення значно розвинулося за останні 4 роки @Leon :-) 'Я оновив відповідь. Я вже згадував, що літерал дати не включає елемент часу, але я назвав це більш чітко, як ви заявили. 9i розширена підтримка закінчилася майже 6 років тому ... і була випущена 14 років тому. Це більше не повинно бути актуальним для переважної більшості користувачів.
Бен


6

Висновок,

to_char працює по-своєму

Так,

Завжди використовуйте цей формат YYYY-MM-DD для порівняння замість MM-DD-YY або DD-MM-YYYY або будь-якого іншого формату


4

Ви можете використовувати trunc і to_date таким чином:

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

з вашого запиту:

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

я думаю, що не показувати кількість працівників, яких наймають після 20 червня 1994 року. Якщо ви хочете показати кількість працівників, ви можете використовувати:

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

Я думаю, що для найкращої практики порівняти дати, які можна використовувати:

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

-4

Єдина цитата повинна бути присутня з дати перетворення в символ.

Виберіть співробітника_id, кількість (*)
Від працівника
Де до_часу (службовий_далі_хиред, 'DD-ПН-YY')> '31 -DEC-95 ';

1
Цей SQL використовує неявний формат дати, він не завжди працює.
Джон Хеллер

5
Це добре працює лише для ваших налаштувань NLS_ *, може не працювати на інших клієнтах або серверах. Прийнята відповідь пояснює, чому важливий чіткий формат дати.
Джон Хеллер

Цей метод порівнює рядки, а не дати. Другий рядок починається з "3", тому порівняння працює як "алфавітний порядок". Цікаво, що такий тип порівняння насправді працює (начебто випадково), якщо ви використовуєте такий формат, як YYYY-MM-DD. Але звичайно, краще порівняти дати з датами ...
Нік Перкінс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.