Porównanie dat w Oracle SQL


141

Próbuję wyświetlić liczbę pracowników zatrudnionych po 20 czerwca 1994 r., Ale pojawia się błąd z informacją o nieprawidłowym identyfikatorze JUN. Proszę o pomoc, dzięki!

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

1
Należy również zauważyć, że można użyć jednej > <lubBETWEEN '' AND ''
Andrew

Odpowiedzi:


296

31-DEC-95nie jest ciągiem ani nim nie jest 20-JUN-94. To liczby z dodatkowymi rzeczami na końcu. Powinno to być '31-DEC-95'albo '20-JUN-94'- zwrócić uwagę na jeden cytat, '. Umożliwi to wykonanie porównania ciągów.

Jednak nie robisz porównania ciągów; porównujesz daty . Powinieneś przekształcić swój ciąg w datę. Albo używając funkcji wbudowanej TO_DATE(), albo literału daty .

SPOTYKAĆ SIĘ Z KIMŚ()

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

Ta metoda ma kilka niepotrzebnych pułapek

  • Jak zauważono w komentarzach a_horse_with_no_name DEC, niekoniecznie oznacza grudzień. To zależy od twoich NLS_DATE_LANGUAGEi NLS_DATE_FORMATustawień. Aby mieć pewność, że porównanie będzie działać w dowolnej lokalizacji, można zamiast tego użyć modelu formatu daty i godzinyMM
  • Rok 95 jest niedokładny. Wiesz, że masz na myśli rok 1995, ale co by było, gdyby był rok 50, czy to 1950 czy 2050? Zawsze najlepiej jest mówić wprost
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

Literały daty

Literał daty jest częścią standardu ANSI, co oznacza, że ​​nie musisz używać funkcji specyficznej dla Oracle. Używając literału, musisz określić swoją datę w formacie YYYY-MM-DDi nie możesz dołączyć elementu czasu.

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

Pamiętaj, że typ danych Oracle zawiera element czasu, więc data bez części czasu jest równoważna 1995-12-31 00:00:00.

Jeśli chcesz uwzględnić część czasu, musisz użyć literału datownika, który przyjmuje 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'

Dalsza informacja

NLS_DATE_LANGUAGEpochodzi z NLS_LANGUAGEi NLS_DATE_FORMATpochodzi z NLS_TERRITORY. Są one ustawiane podczas początkowego tworzenia bazy danych, ale można je zmienić, zmieniając plik parametrów inicjalizacji - tylko jeśli jest to naprawdę wymagane - lub na poziomie sesji przy użyciu ALTER SESSIONskładni. Na przykład:

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

To znaczy:

  • DD numeryczny dzień miesiąca, 1-31
  • MM numeryczny miesiąc roku, 01-12 (styczeń to 01)
  • YYYY4-cyfrowy rok - moim zdaniem jest to zawsze lepsze niż rok 2-cyfrowy, YYponieważ nie ma wątpliwości, do jakiego wieku się odnosisz.
  • HH24 godzina dnia, 0 - 23
  • MI minuta godziny, 0 - 59
  • SS sekunda minuty, 0-59

Możesz sprawdzić swój bieżący język i ustawienia języka daty, wysyłając zapytanie, V$NLS_PARAMETERSsa pełną gamę prawidłowych wartości, wysyłając zapytanie V$NLS_VALID_VALUES.

Dalsza lektura


Nawiasem mówiąc, jeśli chcesz count(*), musisz pogrupować wedługemployee_id

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

To daje liczbę na employee_id .


13
+1 za użycie maski formatu w to_date (). Pamiętaj, że może to nadal nie działać w innych środowiskach z powodu różnych ustawień języka. DECniekoniecznie zawsze jest ważnym miesiącem. Zwykle lepiej jest używać liczb zamiast nazw
a_horse_with_no_name

1
Państwo może określić czas z ANSI dosłowny - po prostu trzeba określać timestampdosłowne zamiast datedosłowny: timestamp '2015-01-30 19:42:04' (bo w ANSI SQL A datetyp danych nie ma czasu, tylko timestamptyp danych robi).
a_horse_with_no_name

1
Literały daty ANSI to naprawdę zwięzły sposób na porównanie konieczności każdorazowego wpisywania TO_DATE i Date-Format. Dobre dla programistów LAZY takich jak ja. Jedna rzecz, na którą należy zwrócić uwagę, DATE 2016-04-01to 2016-04-01 00:00:00naprawdę środki . I myślę, że ta składnia działa od Oracle 9i, ponieważ jest to miejsce, w którym składnia ANSI-SQL została wprowadzona do Oracle.
LeOn - Han Li

1
Moje myślenie znacznie się rozwinęło w ciągu ostatnich 4 lat @Leon :-) „Zaktualizowałem odpowiedź. Wspomniałem, że literał daty nie zawiera elementu czasu, ale powiedziałem o tym bardziej wyraźnie, jak powiedziałeś. Rozszerzone wsparcie dla 9i zakończyło się prawie 6 lat temu ... i zostało wydane 14 lat temu. To nie powinno już być istotne dla większości użytkowników.
Ben


6

Wniosek,

to_char działa na swój sposób

Więc,

Zawsze używaj tego formatu RRRR-MM-DD do porównania zamiast MM-DD-RR lub DD-MM-RRRR lub innego formatu


4

Możesz użyć trunc i to_date w następujący sposób:

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

z twojego zapytania:

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

myślę, że nie ma na celu wyświetlenia liczby pracowników zatrudnionych po 20 czerwca 1994 roku. Jeśli chcesz wyświetlić liczbę pracowników, możesz użyć:

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

Myślę, że najlepszą praktyką jest porównywanie dat:

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

-4

Musi tam być pojedynczy cudzysłów, ponieważ data została przekonwertowana na znak.

Wybierz Employer_id, count (*)
Od pracownika
Gdzie to_char (data_zatrudnienia_pracownika, 'DD-MON-RR')> '31 -DEC-95 ';

1
Ten SQL używa niejawnego formatu daty, nie zawsze będzie działać.
Jon Heller

5
Działa dobrze tylko dla określonych ustawień NLS_ *, może nie działać na innych klientach lub serwerach. Przyjęta odpowiedź wyjaśnia, dlaczego wyraźny format daty jest ważny.
Jon Heller

Ta metoda porównuje ciągi, a nie daty. Drugi ciąg zaczyna się od „3”, więc porównanie działa jak „porządek alfabetyczny”. Co ciekawe, ten rodzaj porównania faktycznie działa (jakby przez przypadek), jeśli używasz formatu takiego jak RRRR-MM-DD. Ale oczywiście lepiej jest porównywać daty z datami ...
Nick Perkins
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.