Создайте дату из месяца и года дня с помощью T-SQL
Я пытаюсь преобразовать дату с отдельными частями, такими как 12, 1, 2007, в datetime в SQL Server 2005. Я попробовал следующее:
CAST(DATEPART(year, DATE)+'-'+ DATEPART(month, DATE) +'-'+ DATEPART(day, DATE) AS DATETIME)
но это приводит к неправильной дате. Как правильно превратить три значения даты в правильный формат datetime.
14 ответов
предполагая, что y, m, d
все int
, как:
CAST(CAST(y AS varchar) + '-' + CAST(m AS varchar) + '-' + CAST(d AS varchar) AS DATETIME)
см. мой другой ответ для SQL Server 2012 и выше
попробуйте это:
Declare @DayOfMonth TinyInt Set @DayOfMonth = 13
Declare @Month TinyInt Set @Month = 6
Declare @Year Integer Set @Year = 2006
-- ------------------------------------
Select DateAdd(day, @DayOfMonth - 1,
DateAdd(month, @Month - 1,
DateAdd(Year, @Year-1900, 0)))
Он также работает, добавил преимущество не делать никаких преобразований строк, поэтому это чистая арифметическая обработка (очень быстрая), и она не зависит от формата даты Это основывается на том факте, что внутреннее представление SQL Server для значений datetime и smalldatetime представляет собой значение из двух частей, первая часть которого представляет собой целое число, представляющее количество дней с 1 января 1900 года, а вторая часть-десятичную дробь, представляющую дробную часть часть одного дня (для времени) - - - поэтому целое значение 0 (ноль) всегда переводится непосредственно в полночь 1 января 1900 года...
или, благодаря предложению от @brinary,
Select DateAdd(yy, @Year-1900,
DateAdd(m, @Month - 1, @DayOfMonth - 1))
Отредактировано Октябрь 2014. Как отметил @cade Roux, SQL 2012 теперь имеет встроенную функцию:DATEFROMPARTS(year, month, day)
это то же самое.
отредактировано 3 окт. 2016, (спасибо @bambams за это замечание и @brinary за его исправление), последнее решение, предложенное @brinary. кажется, не работает в високосные годы, если сначала не выполняется добавление лет
select dateadd(month, @Month - 1,
dateadd(year, @Year-1900, @DayOfMonth - 1));
SQL Server 2012 имеет замечательную и долгожданную новую функцию DATEFROMPARTS (которая вызовет ошибку, если дата недействительна - мое главное возражение против решения этой проблемы на основе DATEADD):
http://msdn.microsoft.com/en-us/library/hh213228.aspx
DATEFROMPARTS(ycolumn, mcolumn, dcolumn)
или
DATEFROMPARTS(@y, @m, @d)
или используя только одну функцию dateadd:
DECLARE @day int, @month int, @year int
SELECT @day = 4, @month = 3, @year = 2011
SELECT dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1)
Sql Server 2012 имеет функцию, которая будет создавать дату на основе частей (DATEFROMPARTS). Для остальных из нас, вот функция db, которую я создал, которая определит дату из частей (спасибо @Charles)...
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[func_DateFromParts]'))
DROP FUNCTION [dbo].[func_DateFromParts]
GO
CREATE FUNCTION [dbo].[func_DateFromParts]
(
@Year INT,
@Month INT,
@DayOfMonth INT,
@Hour INT = 0, -- based on 24 hour clock (add 12 for PM :)
@Min INT = 0,
@Sec INT = 0
)
RETURNS DATETIME
AS
BEGIN
RETURN DATEADD(second, @Sec,
DATEADD(minute, @Min,
DATEADD(hour, @Hour,
DATEADD(day, @DayOfMonth - 1,
DATEADD(month, @Month - 1,
DATEADD(Year, @Year-1900, 0))))))
END
GO
вы можете назвать это так...
SELECT dbo.func_DateFromParts(2013, 10, 4, 15, 50, DEFAULT)
возвращает...
2013-10-04 15:50:00.000
попробуйте преобразовать вместо CAST.
CONVERT позволяет третий параметр, указывающий формат даты.
список форматов здесь:http://msdn.microsoft.com/en-us/library/ms187928.aspx
обновление после того, как другой ответ был выбран в качестве "правильного" ответа:
Я действительно не понимаю, почему выбран ответ, который явно зависит от настроек NLS на вашем сервере, без указания этого ограничения.
вы также можете использовать
select DATEFROMPARTS(year, month, day) as ColDate, Col2, Col3
From MyTable Where DATEFROMPARTS(year, month, day) Between @DateIni and @DateEnd
работает в SQL с ver.2012 и AzureSQL
безопаснее и аккуратнее использовать явную отправную точку '19000101'
create function dbo.fnDateTime2FromParts(@Year int, @Month int, @Day int, @Hour int, @Minute int, @Second int, @Nanosecond int)
returns datetime2
as
begin
-- Note! SQL Server 2012 includes datetime2fromparts() function
declare @output datetime2 = '19000101'
set @output = dateadd(year , @Year - 1900 , @output)
set @output = dateadd(month , @Month - 1 , @output)
set @output = dateadd(day , @Day - 1 , @output)
set @output = dateadd(hour , @Hour , @output)
set @output = dateadd(minute , @Minute , @output)
set @output = dateadd(second , @Second , @output)
set @output = dateadd(ns , @Nanosecond , @output)
return @output
end
Если вы не хотите держать строки из него, это также работает (поместите его в функцию):
DECLARE @Day int, @Month int, @Year int
SELECT @Day = 1, @Month = 2, @Year = 2008
SELECT DateAdd(dd, @Day-1, DateAdd(mm, @Month -1, DateAdd(yy, @Year - 2000, '20000101')))
Я добавляю однострочное решение, если вам нужно datetime от обеих частей даты и времени:
select dateadd(month, (@Year -1900)*12 + @Month -1, @DayOfMonth -1) + dateadd(ss, @Hour*3600 + @Minute*60 + @Second, 0) + dateadd(ms, @Millisecond, 0)
попробовать
CAST(STR(DATEPART(year, DATE))+'-'+ STR(DATEPART(month, DATE)) +'-'+ STR(DATEPART(day, DATE)) AS DATETIME)
для версий SQL Server ниже 12 я могу рекомендовать использование CAST
в сочетании с SET DATEFORMAT
-- 26 February 2015
SET DATEFORMAT dmy
SELECT CAST('26-2-2015' AS DATE)
SET DATEFORMAT ymd
SELECT CAST('2015-2-26' AS DATE)
как вы создаете эти строки до вас
попробуйте выполнить этот запрос:
SELECT SUBSTRING(CONVERT(VARCHAR,JOINGDATE,103),7,4)AS
YEAR,SUBSTRING(CONVERT(VARCHAR,JOINGDATE,100),1,2)AS
MONTH,SUBSTRING(CONVERT(VARCHAR,JOINGDATE,100),4,3)AS DATE FROM EMPLOYEE1
результат:
2014 Ja 1
2015 Ja 1
2014 Ja 1
2015 Ja 1
2012 Ja 1
2010 Ja 1
2015 Ja 1
Я лично предпочитаю подстроку, поскольку она обеспечивает параметры очистки и возможность разбить строку по мере необходимости. Предполагается, что данные имеют формат "dd, mm, yyyy".
--2012 and above
SELECT CONCAT (
RIGHT(REPLACE(@date, ' ', ''), 4)
,'-'
,RIGHT(CONCAT('00',SUBSTRING(REPLACE(@date, ' ', ''), CHARINDEX(',', REPLACE(@date, ' ', '')) + 1, LEN(REPLACE(@date, ' ', '')) - CHARINDEX(',', REPLACE(@date, ' ', '')) - 5)),2)
,'-'
,RIGHT(CONCAT('00',SUBSTRING(REPLACE(@date, ' ', ''), 1, CHARINDEX(',', REPLACE(@date, ' ', '')) - 1)),2)
)
--2008 and below
SELECT RIGHT(REPLACE(@date, ' ', ''), 4)
+'-'
+RIGHT('00'+SUBSTRING(REPLACE(@date, ' ', ''), CHARINDEX(',', REPLACE(@date, ' ', '')) + 1, LEN(REPLACE(@date, ' ', '')) - CHARINDEX(',', REPLACE(@date, ' ', '')) - 5),2)
+'-'
+RIGHT('00'+SUBSTRING(REPLACE(@date, ' ', ''), 1, CHARINDEX(',', REPLACE(@date, ' ', '')) - 1),2)
вот демонстрация того, как можно подать в суд, если данные хранятся в столбце. Излишне говорить, что его идеально проверить результирующий набор перед применением к столбцу
DECLARE @Table TABLE (ID INT IDENTITY(1000,1), DateString VARCHAR(50), DateColumn DATE)
INSERT INTO @Table
SELECT'12, 1, 2007',NULL
UNION
SELECT'15,3, 2007',NULL
UNION
SELECT'18, 11 , 2007',NULL
UNION
SELECT'22 , 11, 2007',NULL
UNION
SELECT'30, 12, 2007 ',NULL
UPDATE @Table
SET DateColumn = CONCAT (
RIGHT(REPLACE(DateString, ' ', ''), 4)
,'-'
,RIGHT(CONCAT('00',SUBSTRING(REPLACE(DateString, ' ', ''), CHARINDEX(',', REPLACE(DateString, ' ', '')) + 1, LEN(REPLACE(DateString, ' ', '')) - CHARINDEX(',', REPLACE(DateString, ' ', '')) - 5)),2)
,'-'
,RIGHT(CONCAT('00',SUBSTRING(REPLACE(DateString, ' ', ''), 1, CHARINDEX(',', REPLACE(DateString, ' ', '')) - 1)),2)
)
SELECT ID,DateString,DateColumn
FROM @Table