2008-10-14 30 views
9

Estoy intentando escribir un procedimiento almacenado que selecciona columnas de una tabla y agrega 2 columnas adicionales al ResultSet. Estas 2 columnas adicionales son el resultado de las conversiones en un campo de la tabla que es un campo de fecha y hora.Formateo personalizado de fecha/hora en SQL Server

El campo de formato de fecha y hora tiene el siguiente formato 'YYYY-MM-DD HH: MM: SS.S'

Los 2 campos adicionales que debe estar en el siguiente formato:

  1. DDMMM
  2. HHMMT, donde T es 'A' para am y 'P' para pm

Ejemplo: Si los datos en el campo era '2008-10-12 13: 19: 12.0', entonces los campos extraídos debe contener:

  1. 12OCT
  2. 0119P

He intentado usar formatos de cadena CONVERTIR, pero ninguno de los formatos coincide con el resultado que quiero obtener. Estoy pensando en la extracción de los datos de campo a través de CONVERT y luego en REEMPLAZAR, pero seguramente necesito ayuda aquí, ya que no estoy seguro.

¿Alguien versado en procedimientos almacenados podría ayudarme aquí? Gracias!

+1

Estos resultados de salida que está buscando me recuerdan a las fechas en la parte inferior de la sopa latas Solo necesita una sp si va a hacer esto repetidamente. – StingyJack

+0

Tiene razón, voy a hacer esto repetidamente. – Pascal

+0

Consulte "SQL Server", no "SQL", porque las diferentes bases de datos tienen una forma diferente de formatear las fechas. –

Respuesta

4

Si dt ​​es la columna de fecha y hora, y luego

Para 1:

SUBSTRING(CONVERT(varchar, dt, 13), 1, 2) 
    + UPPER(SUBSTRING(CONVERT(varchar, dt, 13), 4, 3)) 

Para 2:

SUBSTRING(CONVERT(varchar, dt, 100), 13, 2) 
    + SUBSTRING(CONVERT(varchar, dt, 100), 16, 3) 
+0

Gracias por su respuesta. ¡Me ayudo mucho! Utilicé el formato 106, en lugar de 13 para la primera parte. Es posible hacer un relleno cero en el lado izquierdo para el formato 2 (tiempo), si el tiempo indicado es algo así como 924P. – Pascal

+0

Definitivamente es posible, pero cómo rellenar con ceros en SQL Server es una pregunta diferente. Aquí hay un ejemplo: http://stackoverflow.com/questions/16760900/pad-a-string-with-leading-zeros-so-its-3-characters-long-in-sql-server-2008 – Glazed

22

Uso DATENAME y envolver la lógica de una función, no un procedimiento almacenado

declare @myTime as DateTime 

set @myTime = GETDATE() 

select @myTime 

select DATENAME(day, @myTime) + SUBSTRING(UPPER(DATENAME(month, @myTime)), 0,4) 

Devuelve "14OCT"

Si es posible, intente no utilizar operaciones basadas en Caracteres/Cadenas cuando trabaje con fechas. Son numéricos (un flotante) y el rendimiento sufrirá esas conversiones de tipo de datos.

Dig estas conversiones prácticos que he recopilado a lo largo de los años ...

/* Common date functions */ 
--//This contains common date functions for MSSQL server 

/*Getting Parts of a DateTime*/ 
    --//gets the date only, 20x faster than using Convert/Cast to varchar 
    --//this has been especially useful for JOINS 
    SELECT (CAST(FLOOR(CAST(GETDATE() as FLOAT)) AS DateTime)) 

    --//gets the time only (date portion is '1900-01-01' and is considered the "0 time" of dates in MSSQL, even with the datatype min value of 01/01/1753. 
    SELECT (GETDATE() - (CAST(FLOOR(CAST(GETDATE() as FLOAT)) AS DateTime))) 


/*Relative Dates*/ 
--//These are all functions that will calculate a date relative to the current date and time 
    /*Current Day*/ 
    --//now 
    SELECT (GETDATE()) 

    --//midnight of today 
    SELECT (DATEADD(ms,-4,(DATEADD(dd,DATEDIFF(dd,0,GETDATE()) + 1,0)))) 

    --//Current Hour 
    SELECT DATEADD(hh,DATEPART(hh,GETDATE()),CAST(FLOOR(CAST(GETDATE() AS FLOAT)) as DateTime)) 

    --//Current Half-Hour - if its 9:36, this will show 9:30 
    SELECT DATEADD(mi,((DATEDIFF(mi,(CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime)), GETDATE()))/30) * 30,(CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime))) 

    /*Yearly*/ 
    --//first datetime of the current year 
    SELECT (DATEADD(yy,DATEDIFF(yy,0,GETDATE()),0)) 

    --//last datetime of the current year 
    SELECT (DATEADD(ms,-4,(DATEADD(yy,DATEDIFF(yy,0,GETDATE()) + 1,0)))) 

    /*Monthly*/ 
    --//first datetime of current month 
    SELECT (DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0)) 

    --//last datetime of the current month 
    SELECT (DATEADD(ms,-4,DATEADD(mm,1,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0)))) 

    --//first datetime of the previous month 
    SELECT (DATEADD(mm,DATEDIFF(mm,0,GETDATE()) -1,0)) 

    --//last datetime of the previous month 
    SELECT (DATEADD(ms, -4,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))) 

    /*Weekly*/ 
    --//previous monday at 12AM 
    SELECT (DATEADD(wk,DATEDIFF(wk,0,GETDATE()) -1 ,0)) 

    --//previous friday at 11:59:59 PM 
    SELECT (DATEADD(ms,-4,DATEADD(dd,5,DATEADD(wk,DATEDIFF(wk,0,GETDATE()) -1 ,0)))) 

    /*Quarterly*/ 
    --//first datetime of current quarter 
    SELECT (DATEADD(qq,DATEDIFF(qq,0,GETDATE()),0)) 

    --//last datetime of current quarter 
    SELECT (DATEADD(ms,-4,DATEADD(qq,DATEDIFF(qq,0,GETDATE()) + 1,0))) 
+0

Gracias por sus consejos y útil referencia de función. ¡Debería ser útil! – Pascal

0

vas a necesitar DATEPART aquí. Puede concatenar los resultados de las llamadas DATEPART juntas.

Para obtener las abreviaturas de los meses, es posible que pueda usar DATENAME; si eso no funciona para usted, puede usar una declaración CASE en DATEPART.

DATEPART también funciona para el campo de tiempo.

Puedo pensar en un par de maneras de obtener el indicador AM/PM, incluida la comparación de nuevas fechas creadas a través de DATEPART o el cálculo del total de segundos transcurridos en el día y compararlo con los umbrales AM/PM conocidos.

6

No respondiendo a su pregunta específicamente, pero no es algo que deba ser manejado por la capa de presentación de su aplicación. Hacerlo de la manera que describe crea un procesamiento adicional en el final de la base de datos y agrega tráfico de red adicional (suponiendo que la base de datos exista en una máquina diferente a la aplicación), para algo que pueda calcularse fácilmente en el lado de la aplicación, con una fecha más rica procesando librerías, además de ser más independiente del idioma, especialmente en el caso de su primer ejemplo que contiene el nombre del mes abreviado. De todos modos, las respuestas que te dan los demás deben indicarte la dirección correcta si aún decides seguir esta ruta.

+1

Sí, tiene toda la razón y me hago eco de sus sentimientos aquí, pero hay personas por encima de mí que quieren que esto se maneje en la SP. De lo contrario, probablemente no haría esta pregunta. :) – Pascal

+0

Algunas veces desea aplicar un estándar en el límite de su base de datos, y algunas veces desea combinar columnas en columnas de salida más cortas, y es más eficiente hacer que SQL Server lo haga antes de enviarlo por cable. –

+0

Dicho esto, si debe hacer esto, ajuste el código de formato en una función propia para que el formato se pueda duplicar fácilmente en las consultas/procedimientos almacenados en los que necesite usarlo. – Kibbee

4

El campo de formato de fecha y hora tiene el siguiente formato 'AAAA-MM-DD HH: MM: SS.S'

Esta afirmación es falsa. Así es como Enterprise Manager o SQL Server elige mostrar la fecha. Internamente es un valor binario de 8 bytes, por lo que algunas de las funciones publicadas por Andrew funcionarán muy bien.

Kibbee también tiene un punto válido, y en un mundo perfecto estaría de acuerdo con él. Sin embargo, a veces desea vincular los resultados de la consulta directamente para mostrar el control o los widgets, y no existe la posibilidad de formatear. Y a veces la capa de presentación vive en un servidor web que está incluso más ocupado que la base de datos. Con eso en mente, no es necesariamente algo malo saber cómo hacer esto en SQL.

1

Yes Depart es una solución para eso, pero creo que este tipo de métodos son viajes largos.

SQL Server:

SELECT CAST(DATEPART(DD,GETDATE()) AS VARCHAR)+'/' 
+CAST(DATEPART(MM,GETDATE()) AS VARCHAR) 
+'/'+CAST(DATEPART(YYYY,GETDATE()) AS VARCHAR) 
+' '+CAST(DATEPART(HH,GETDATE()) AS VARCHAR) 
+':'+CAST(DATEPART(MI,GETDATE()) AS VARCHAR) 

Oracle:

Select to_char(sysdate,'DD/MM/YYYY HH24:MI') from dual 

Usted puede escribir su propia función de esta manera usted puede deshacerse de este lío;

http://sql.dzone.com/news/custom-date-formatting-sql-ser

select myshortfun(getdate(),myformat) 
GO 
+2

Si va a bajar la fecha camino, también puede necesitar ceros a la izquierda en el día: DERECHA ('00 '+ CONVERT (NVARCHAR (2), DATEPART (DAY, GETDATE())), 2), – SteveCav

+0

Shame SQL Server no tiene esta misma función. ¡Solo mira esa estúpida sintaxis! – NickG

0

en MS SQL Server que puede hacer: DATEFORMAT

SET ymd

año, meses, día,

0

Si es algo más específico como DateKey (yyyymmdd) que necesita para modelos dimensionales, es s uggest algo sin ningún tipo de moldes/convierte:

DECLARE @DateKeyToday int = (SELECT 10000 * DATEPART(yy,GETDATE()) + 100 * DATEPART(mm,GETDATE()) + DATEPART(dd,GETDATE())); 
PRINT @DateKeyToday 
0

estoy añadiendo esta respuesta (para mí) como relevantes para el formato personalizado.

Para yyyy_MM_dd subrayado

REPLACE(SUBSTRING(CONVERT(VARCHAR, @dt, 120), 1, 10),'-','_') 
5

Se puede utilizar el siguiente comando en el servidor SQL para que sea:

select FORMAT(getdate(), N'yyyy-MM-ddThh:mm:ss') 
+2

Debería ser 'select FORMAT (getdate(), N'yyyy-MM-ddThh: mm: ss ')' – Laymain

+0

Esta respuesta solo es válida para> = 2014 versiones –

+1

The ['FORMAT'] (https: // docs El comando .microsoft.com/en-us/sql/t-sql/functions/format-transact-sql) usa poco m para minutos y gran M para días. Consulte [Tipos de formato] (https://msdn.microsoft.com/library/26etazsy.aspx) vinculado en el primer artículo. – Trisped