Ответ 1
Предполагая y, m, d
все int
, как насчет:
CAST(CAST(y AS varchar) + '-' + CAST(m AS varchar) + '-' + CAST(d AS varchar) AS DATETIME)
См. мой другой ответ для SQL Server 2012 и выше
Я пытаюсь преобразовать дату с отдельными частями, такими как 12, 1, 2007, в datetime в SQL Server 2005. Я пробовал следующее:
CAST(DATEPART(year, DATE)+'-'+ DATEPART(month, DATE) +'-'+ DATEPART(day, DATE) AS DATETIME)
но это приводит к неправильной дате. Каков правильный способ превратить три значения даты в правильный формат даты и времени.
Предполагая 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
Попробуйте CONVERT вместо 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')))
Я добавляю однострочное решение, если вам нужна дата и время из частей даты и времени:
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
Если вы используете SQL 2012 или выше, вы можете использовать следующее:
SELECT DATEADD(DAY, 1, EOMONTH(@somedate, -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