Comparación de fechas en Oracle SQL

141

Estoy tratando de que muestre el número de empleados que son contratados después del 20 de junio de 1994, pero recibo un error que dice "Identificador inválido JUN". ¡Por favor ayuda, gracias!

Select employee_id, count(*)
From Employee
Where to_char(employee_date_hired, 'DD-MON-YY') > 31-DEC-95; 
usuario1336830
fuente
1
Tenga en cuenta también que puede usar cualquiera > <oBETWEEN '' AND ''
Andrew

Respuestas:

296

31-DEC-95no es una cadena, ni lo es 20-JUN-94. Son números con algunas cosas adicionales agregadas al final. Esto debería ser '31-DEC-95'o '20-JUN-94'- tenga en cuenta la comilla simple, '. Esto te permitirá hacer una comparación de cadenas.

Sin embargo, no estás haciendo una comparación de cadenas; Estás haciendo una comparación de fechas . Debes transformar tu cadena en una fecha. Ya sea utilizando la TO_DATE()función incorporada o un literal de fecha .

HASTA LA FECHA()

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

Este método tiene algunas trampas innecesarias

  • Como a_horse_with_no_name señaló en los comentarios, DECno necesariamente significa diciembre. Depende de tu NLS_DATE_LANGUAGEy la NLS_DATE_FORMATconfiguración. Para asegurarse de que su comparación con el trabajo en cualquier configuración regional que se puede utilizar el modelo de formato de fecha y hora MM en vez
  • El año '95 es inexacto. Sabes que te refieres a 1995, pero ¿y si fuera '50, es 1950 o 2050? Siempre es mejor ser explícito
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

Literales de fecha

Un literal de fecha es parte del estándar ANSI, lo que significa que no tiene que usar una función específica de Oracle. Cuando utilice un literal, debe especificar su fecha en el formato YYYY-MM-DDy no puede incluir un elemento de hora.

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

Recuerde que el tipo de datos de fecha de Oracle incluye un elemento de tiempo, por lo que la fecha sin una porción de tiempo es equivalente a 1995-12-31 00:00:00.

Si desea incluir una porción de tiempo, entonces debería usar un literal de marca de tiempo, que toma el 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'

Más información

NLS_DATE_LANGUAGEse deriva de NLS_LANGUAGEy NLS_DATE_FORMATse deriva de NLS_TERRITORY. Estos se configuran cuando creó inicialmente la base de datos, pero pueden modificarse cambiando el archivo de parámetros de inicialización, solo si es realmente necesario, o en el nivel de sesión utilizando la ALTER SESSIONsintaxis. Por ejemplo:

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

Esto significa:

  • DD día numérico del mes, 1 - 31
  • MM mes numérico del año, 01-12 (enero es 01)
  • YYYYAño de 4 dígitos: en mi opinión, esto siempre es mejor que un año de 2 dígitos, YYya que no hay confusión con el siglo al que te refieres.
  • HH24 hora del día, 0-23
  • MI minuto de la hora, 0 - 59
  • SS segundo del minuto, 0-59

Puede averiguar su idioma actual y la configuración del idioma de la fecha consultando V$NLS_PARAMETERSsy la gama completa de valores válidos consultando V$NLS_VALID_VALUES.

Otras lecturas


Por cierto, si quieres, count(*)debes agrupar poremployee_id

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

Esto te da la cuenta por employee_id .

Ben
fuente
13
+1 para usar una máscara de formato en to_date (). Tenga en cuenta que esto todavía puede fallar en diferentes entornos debido a diferentes configuraciones de idioma. DECNo es necesariamente siempre un mes válido. Por lo general, es mejor usar números en lugar de nombres
a_horse_with_no_name
1
Usted puede especificar una hora con un literal ANSI - sólo tiene que especificar un timestampliteral en lugar de un dateliteral: timestamp '2015-01-30 19:42:04' (porque en ANSI SQL a El datetipo de datos no tiene un momento, sólo el timestamptipo de datos lo hace).
a_horse_with_no_name
1
Los literales de fecha ANSI son realmente una forma concisa comparando tener que escribir TO_DATE y Date-Format cada vez. Bueno para desarrolladores LAZY como yo. Una cosa a notar es los DATE 2016-04-01medios 2016-04-01 00:00:00realmente. Y creo que esta sintaxis funciona desde Oracle 9i, ya que aquí es donde se introdujo la sintaxis ANSI-SQL en Oracle.
LeOn - Han Li
1
Mi pensamiento ha evolucionado significativamente en los últimos 4 años @Leon :-) 'He actualizado la respuesta. Mencioné que un literal de fecha no incluía un elemento de tiempo, pero lo he llamado de manera más explícita, como usted ha dicho. El soporte extendido de 9i terminó hace casi 6 años ... y se lanzó hace 14 años. Ya no debería ser relevante para la gran mayoría de los usuarios.
Ben
6

Conclusión,

to_char trabaja a su manera

Entonces,

Utilice siempre este formato AAAA-MM-DD para comparar en lugar de MM-DD-AA o DD-MM-AAAA o cualquier otro formato

akshay gulawane
fuente
4

Puede usar trunc y to_date de la siguiente manera:

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.
fuente
2

de su consulta:

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

creo que no es para mostrar la cantidad de empleados que son contratados después del 20 de junio de 1994. si desea mostrar la cantidad de empleados, puede usar:

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

Creo que las mejores prácticas para comparar fechas pueden usar:

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

La comilla simple debe estar allí, ya que la fecha se convirtió en carácter.

Seleccione employee_id, count (*)
Del empleado
Where to_char (employee_date_hired, 'DD-MON-YY')> '31 -DEC-95 ';
MVB
fuente
1
Este SQL utiliza un formato de fecha implícito, no siempre funcionará.
Jon Heller
55
Solo funciona bien para su configuración específica de NLS_ *, puede que no funcione en otros clientes o servidores. La respuesta aceptada explica por qué es importante un formato de fecha explícito.
Jon Heller
Este método compara cadenas, no fechas. La segunda cadena comienza con un "3", por lo que la comparación funciona como "orden alfabético". Curiosamente, este tipo de comparación realmente funciona (por accidente) si utiliza un formato como AAAA-MM-DD. Pero, por supuesto, es mejor comparar fechas con fechas ...
Nick Perkins