Настраиваемое форматирование даты / времени в SQL Server

Я пытаюсь написать хранимую процедуру, которая выбирает столбцы из таблицы и добавляет 2 дополнительных столбца в ResultSet. Эти 2 дополнительных столбца являются результатом преобразований в поле таблицы, которое является полем Datetime.

Поле формата Datetime имеет следующий формат: "ГГГГ-ММ-ДД ЧЧ: ММ: СС.S"

2 дополнительных поля, которые должны быть в следующем формате:

  1. DDMMM
  2. ЧЧММТ, где Т это "А" для утра и "Р" для вечера

Пример: если данные в поле были "2008-10-12 13:19:12.0", то извлеченные поля должны содержать:

  1. 12OCT
  2. 0119P

Я пытался использовать строковые форматы CONVERT, но ни один из форматов не соответствует выводу, который я хочу получить. Я думаю о том, как извлекать полевые данные с помощью CONVERT, а затем использовать REPLACE, но мне, безусловно, нужна некоторая помощь, поскольку я не уверен.

Может ли кто-нибудь, хорошо разбирающийся в хранимых процедурах, помочь мне здесь? Спасибо!

10 ответов

Решение

Если dt - ваш столбец даты и времени, то

За 1:

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

Для 2:

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

Используйте DATENAME и заключите логику в функцию, а не в сохраненный процесс

declare @myTime as DateTime

set @myTime = GETDATE()

select @myTime

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

Возвращает "14OCT"

Старайтесь не использовать никакие символьные / строковые операции, если это возможно, при работе с датами. Они являются числовыми (с плавающей запятой), и производительность будет зависеть от этих преобразований типов данных.

Копайте эти удобные преобразования, которые я собрал за эти годы...

/* 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)))

Вы можете использовать следующую команду на сервере SQL, чтобы сделать это:

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

Не отвечая конкретно на ваш вопрос, но разве это не то, что должно обрабатываться на уровне представления вашего приложения. Выполнение так, как вы описываете, создает дополнительную обработку на стороне базы данных, а также добавляет дополнительный сетевой трафик (при условии, что база данных существует на другом компьютере, чем приложение), для чего-то, что может быть легко вычислено на стороне приложения, с более богатой датой обрабатывать библиотеки, а также быть более независимыми от языка, особенно в случае вашего первого примера, который содержит сокращенное название месяца. В любом случае, ответы, которые вам дают другие, должны указывать вам правильное направление, если вы все же решите пойти по этому пути.

Поле формата Datetime имеет следующий формат: "ГГГГ-ММ-ДД ЧЧ: ММ: СС.S"

Это утверждение неверно. Именно так Enterprise Manager или SQL Server выбирают показ даты. Внутренне это 8-байтовое двоичное значение, поэтому некоторые функции, опубликованные Эндрю, будут работать так хорошо.

Кибби также делает правильное замечание, и в идеальном мире я бы с ним согласился. Однако иногда вы хотите связать результаты запроса напрямую с отображением элемента управления или виджетов, и на самом деле нет никакой возможности выполнить какое-либо форматирование. И иногда слой представления живет на веб-сервере, который даже более загружен, чем база данных. Имея это в виду, не обязательно плохо знать, как это сделать в SQL.

Да, отправление - решение для этого, но я думаю, что такие методы - долгие поездки!

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

Таким образом, вы можете написать свою собственную функцию, чтобы избавиться от этого беспорядка;

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

select myshortfun(getdate(),myformat)
GO

Я добавляю этот ответ (для себя) как имеющий отношение к пользовательскому форматированию.

Для подчеркивания yyyy_MM_dd

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

Вам понадобится DATEPART здесь. Вы можете объединить результаты вызовов DATEPART вместе.

Чтобы получить сокращения месяца, вы можете использовать DATENAME; если это не работает для вас, вы можете использовать оператор CASE на DATEPART.

DATEPART также работает для поля времени.

Я могу подумать о нескольких способах получения индикатора AM/PM, включая сравнение новых дат, построенных с помощью DATEPART, или вычисление общего количества секунд, прошедших за день, и сравнение их с известными пороговыми значениями AM/PM.

В MS SQL Server вы можете сделать:

SET DATEFORMAT ymd

год месяц день,

Если это что-то более конкретное, как DateKey (yyyymmdd) что вам нужно для размерных моделей, я предлагаю что-то без каких-либо преобразований:

DECLARE @DateKeyToday int = (SELECT 10000 * DATEPART(yy,GETDATE()) + 100 * DATEPART(mm,GETDATE()) + DATEPART(dd,GETDATE()));
PRINT @DateKeyToday
Другие вопросы по тегам