Пользовательское форматирование даты / времени в SQL Server - PullRequest
12 голосов
/ 14 октября 2008

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

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

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

  1. DDMMM
  2. ЧЧММТ, где Т - «А» для часа и «Р» - для вечера.

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

  1. 12OCT
  2. 0119P

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

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

Ответы [ 10 ]

25 голосов
/ 14 октября 2008

Используйте 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)))
7 голосов
/ 18 июля 2016

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

select FORMAT(getdate(), N'yyyy-MM-ddThh:mm:ss')
6 голосов
/ 14 октября 2008

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

6 голосов
/ 14 октября 2008

Если 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)
4 голосов
/ 14 октября 2008

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

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

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

1 голос
/ 16 июня 2011

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

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
0 голосов
/ 23 февраля 2015

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

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

REPLACE(SUBSTRING(CONVERT(VARCHAR, @dt, 120), 1, 10),'-','_')
0 голосов
/ 07 февраля 2014

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

DECLARE @DateKeyToday int = (SELECT 10000 * DATEPART(yy,GETDATE()) + 100 * DATEPART(mm,GETDATE()) + DATEPART(dd,GETDATE()));
PRINT @DateKeyToday
0 голосов
/ 24 сентября 2013

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

SET DATEFORMAT ymd

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

0 голосов
/ 14 октября 2008

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

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

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

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

...