Confronto di date in Oracle SQL


141

Sto cercando di visualizzarlo per visualizzare il numero di dipendenti assunti dopo il 20 giugno 1994, ma viene visualizzato un errore che indica l'identificatore non valido "JUN". Aiutatemi, grazie!

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

1
Si noti inoltre che è possibile utilizzare > <oBETWEEN '' AND ''
Andrew

Risposte:


296

31-DEC-95non è una stringa, né lo è 20-JUN-94. Sono numeri con alcune cose extra aggiunte alla fine. Questo dovrebbe essere '31-DEC-95'o '20-JUN-94'- notare l'apostrofo, '. Ciò ti consentirà di fare un confronto tra stringhe.

Tuttavia, non stai facendo un confronto tra stringhe; stai facendo un confronto tra le date . Devi trasformare la tua stringa in una data. O utilizzando la TO_DATE()funzione integrata o una data letterale .

AD OGGI()

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

Questo metodo presenta alcune insidie ​​non necessarie

  • Come notato da a_horse_with_no_name nei commenti, DECnon significa necessariamente dicembre. Dipende dal tuo NLS_DATE_LANGUAGEe dalle NLS_DATE_FORMATimpostazioni. Per garantire che il confronto con funzioni in qualsiasi locale, è possibile utilizzare invece il modello di formato datetime MM
  • L'anno '95 è inesatto. Sai che vuoi dire 1995, ma se fosse il '50, quel 1950 o il 2050? È sempre meglio essere espliciti
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

Letterali di data

Una data letterale fa parte dello standard ANSI, il che significa che non è necessario utilizzare una funzione specifica Oracle. Quando si utilizza un valore letterale, è necessario specificare la data nel formato YYYY-MM-DDe non è possibile includere un elemento orario.

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

Ricorda che il tipo di dati della data Oracle include un elemento orario, quindi la data senza una porzione oraria è equivalente a 1995-12-31 00:00:00.

Se si desidera includere una porzione temporale, è necessario utilizzare un valore letterale timestamp, che assume il formato YYYY-MM-DD HH24:MI:SS[.FF0-9]

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

Ulteriori informazioni

NLS_DATE_LANGUAGEè derivato da NLS_LANGUAGEe NLS_DATE_FORMATderiva da NLS_TERRITORY. Questi vengono impostati al momento della creazione iniziale del database ma possono essere modificati modificando il file dei parametri di inializzazione - solo se realmente richiesto - o a livello di sessione utilizzando la ALTER SESSIONsintassi. Per esempio:

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

Questo significa:

  • DD giorno numerico del mese, 1 - 31
  • MM mese numerico dell'anno, 01 - 12 (gennaio è 01)
  • YYYYAnno a 4 cifre - a mio avviso, è sempre meglio di un anno a 2 cifre YYpoiché non c'è confusione con il secolo a cui ti riferisci.
  • HH24 ora del giorno, 0 - 23
  • MI minuto dell'ora, 0 - 59
  • SS secondo del minuto, 0-59

È possibile scoprire la lingua corrente e le impostazioni della lingua della data eseguendo una query V$NLS_PARAMETERSse l'intera gamma di valori validi eseguendo una query V$NLS_VALID_VALUES.

Ulteriori letture


Per inciso, se si desidera che count(*)è necessario raggruppareemployee_id

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

Questo ti dà il conteggio per employee_id .


13
+1 per l'utilizzo di una maschera di formato in to_date (). Si noti che ciò può comunque fallire in ambienti diversi a causa delle diverse impostazioni della lingua. DECnon è necessariamente sempre un mese valido. Di solito è meglio usare numeri anziché nomi
a_horse_with_no_name

1
È possibile specificare un orario con un letterale ANSI: è sufficiente specificare un timestampletterale anziché un dateletterale: timestamp '2015-01-30 19:42:04' (poiché in ANSI SQL un datetipo di dati non ha un tempo, solo il timestamptipo di dati lo fa).
a_horse_with_no_name

1
I letterali della data ANSI sono davvero un modo conciso confrontando la necessità di digitare TO_DATE e Date-Format ogni volta. Buono per gli sviluppatori LAZY come me. Una cosa da notare è davvero il DATE 2016-04-01mezzo 2016-04-01 00:00:00. E penso che questa sintassi funzioni da Oracle 9i poiché è qui che è stata introdotta la sintassi ANSI-SQL in Oracle.
LeOn - Han Li

1
Il mio pensiero si è evoluto in modo significativo negli ultimi 4 anni @Leon :-) 'Ho aggiornato la risposta. Avevo detto che una data letterale non includeva un elemento temporale ma l'ho chiamato più esplicitamente come hai affermato. Il supporto esteso 9i è terminato quasi 6 anni fa ... ed è stato rilasciato 14 anni fa. Non dovrebbe più essere rilevante per la stragrande maggioranza degli utenti.
Ben


6

Conclusione,

to_char funziona a modo suo

Così,

Utilizzare sempre questo formato AAAA-MM-GG per il confronto anziché MM-GG-AA o GG-MM-AAAA o qualsiasi altro formato


4

Puoi usare trunc e to_date come segue:

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

dalla tua richiesta:

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

penso che non mostri il numero di dipendenti assunti dopo il 20 giugno 1994. se vuoi mostrare il numero di dipendenti, puoi usare:

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

Penso che per la migliore pratica sia possibile confrontare le date che è possibile utilizzare:

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

-4

La virgoletta singola deve essere presente, poiché la data è stata convertita in carattere.

Seleziona employee_id, count (*)
Da dipendente
Dove to_char (employee_date_hired, 'DD-MON-YY')> '31 -DEC-95 ';

1
Questo SQL utilizza un formato data implicito, non funzionerà sempre.
Jon Heller,

5
Funziona bene solo per le tue impostazioni NLS_ * specifiche, potrebbe non funzionare su altri client o server. La risposta accettata spiega perché è importante un formato data esplicito.
Jon Heller,

Questo metodo confronta le stringhe, non le date. La seconda stringa inizia con un "3", quindi il confronto funziona come "ordine alfabetico". È interessante notare che questo tipo di confronto funziona effettivamente (una specie di incidente) se si utilizza un formato come AAAA-MM-GG. Ma ovviamente, è meglio confrontare le date con le date ...
Nick Perkins,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.