Пользовательское форматирование даты и времени в SQL Server

StackOverflow https://stackoverflow.com/questions/202243

Вопрос

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

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

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

  1. ДДМММ
  2. HHMMT, где T - это "A" для утра.и буква "Р" для вечера.

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

  1. 12OCT
  2. 0119P

Я пробовал использовать ПРЕОБРАЗОВАНИЕ строковых форматов, но ни один из форматов не соответствует результату, который я хочу получить.Я подумываю о том, чтобы извлечь данные поля с помощью CONVERT, а затем использовать REPLACE, но мне, безусловно, нужна некоторая помощь здесь, поскольку я не уверен.

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

Это было полезно?

Решение

Если dt - это ваш столбец datetime, то

Для 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 server, чтобы сделать это:

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

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

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

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

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

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

SQL СЕРВЕР:

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

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

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

DATEPART также работает для поля time.

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

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

УСТАНОВИТЬ ФОРМАТ ДАТЫ ymd

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

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

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

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

Для подчеркивания гггг_ММ_дд

REPLACE(SUBSTRING(CONVERT(VARCHAR, @dt, 120), 1, 10),'-','_')
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top