ChatGPT解决这个技术问题 Extra ChatGPT

如何仅从 SQL Server DateTime 数据类型返回日期

SELECT GETDATE()

返回:2008-09-22 15:24:13.790

我想要没有时间部分的日期部分:2008-09-22 00:00:00.000

我怎么能得到那个?

需要注意的一点是,SQL Server 2008 包含一个单独的 DATE 数据类型,用于仅存储没有时间组件的日期。更多信息:sql-server-performance.com/articles/dev/datetime_2008_p1.aspx
不要错过 this post 展示了各种时间去除方法的性能测试结果。
@Martin 很奇怪,谢谢,let's try again
不要被选票和接受的答案误导,看看stackoverflow.com/a/126984/1155650
@Rohit您错误地假设2008年是人们关心的唯一版本。 (野外还有更多版本。)选票不言自明。

d
davidsbro
SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, @your_date))

例如

SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))

给我

2008-09-22 00:00:00.000

优点:

不需要 varchar<->datetime 转换

无需考虑语言环境


+1 看起来这个比常用的 double convert() 方法快 35%(我也使用了多年)。好东西。
我可以看到您的解决方案的唯一缺点是,除非您知道它在做什么,否则它有点迟钝。使用双重转换方法使您的意图对未来的代码维护人员更加明显。顺便说一句,我没有对你投反对票。我想我也会开始使用你的方法。谢谢@aku
@pilavdzice 将日期时间设置为当天的午夜确实离开时间。你期待什么结果? datetime 数据类型不能根本没有时间。我认为您将数据存储与用户演示混淆了。如果您想要的只是一种向用户显示没有时间部分(不是零,只是空白)的字符串的方法,那么您只需要 Convert(varchar(30), @Date, 101) 或类似的东西。有关详细信息,请参阅 SQL Server Books Online • Cast and Convert
@user1671639 datetime 数据类型总是同时包含日期和时间,你不能明智地存储一个没有另一个 - 除非你使用 SQL Server 2008,在这种情况下还有单独的“日期”和“时间”数据类型。如果你像这样使用 CONVERT() ,你真的想要一个字符串供以后使用,所以你会被困在那样做 - 尽管如果你使用日期格式化函数而不是切断日期会更好 - 或通过CAST(... AS DATE)CONVERT(DATE, ...),在此页面上经常提到。
我建议将答案更改为 SELECT DATEADD(dd, DATEDIFF(dd, 0, @your_date), 0),因为这样可以将 dd 替换为任何其他 datepart 关键字,从而在任意级别截断您的 datetime
B
BenR

SQLServer 2008 现在有一个“日期”数据类型,它只包含一个没有时间组件的日期。使用 SQLServer 2008 及更高版本的任何人都可以执行以下操作:

SELECT CONVERT(date, GETDATE())

SQL2008 中还有“时间”数据类型,它回答了分离日期和时间问题的另一半。
仅供参考,我对不同的从日期修剪时间的方法进行了基准测试,这是最快的方法。诚然,差异很小,但在大量的执行中显然更快。
关于 sqlserver 2005 的重量?
@Dr.MAF 完成圈子,2008 年前的答案在这里:stackoverflow.com/questions/113045/…
在 SQL 2019 中,首选是什么 - 这个答案还是 CAST 或 CONVERT?
a
abatishchev

如果使用 SQL 2008 及更高版本:

select cast(getdate() as date)

@FredrickGauss:什么类型,日期?您使用什么版本的 SQL Server?
谨防!声明@date1 datetime = '2015-09-30 20:59:59.999';选择演员(@date1 作为日期)返回“2015-10-01”
@Nick:这是日期时间的问题。改用 DateTime2 ,它工作正常。 sqlfiddle.com/#!6/9eecb7/2833
@Nick,为了补充 abatishchev 的回复,由于 DateTime 的限制,您的 @date1 确实是 2015-10-01。尝试不对 Date 进行任何强制转换,它也会产生 2015-10-01declare @date1 datetime = '2015-09-30 23:59:59.999';select @date1 => 2015-10-01
这些易于记忆的 SQL 技巧之一。正如迈克所说,只有 2008 年以后,但是,如果您在某处找到 2005 年和以前的数据库,您可能会遇到很多问题:)
1
11 revs, 7 users 70%

DATEADD 和 DATEDIFF 比 CONVERTing to varchar 要好。两个查询具有相同的执行计划,但执行计划主要与数据访问策略有关,并不总是揭示执行所有部分所花费的 CPU 时间所涉及的隐含成本。如果两个查询都针对具有数百万行的表运行,则使用 DateDiff 的 CPU 时间可以接近 Convert CPU 时间的 1/3!

要查看查询的执行计划:

set showplan_text on
GO 

DATEADD 和 DATEDIFF 都将执行 CONVERT_IMPLICIT。

尽管 CONVERT 解决方案对某些人来说更简单、更易于阅读,但速度较慢。无需转换回 DateTime(这是由服务器隐式完成的)。之后在 DateDiff 方法中也不需要 DateAdd,因为整数结果也将隐式转换回 DateTime。

从日期表中选择转换(varchar,MyDate,101)

  |--Compute Scalar(DEFINE:([Expr1004]=CONVERT(varchar(30),[TEST].[dbo].[DatesTable].[MyDate],101)))
       |--Table Scan(OBJECT:([TEST].[dbo].[DatesTable]))

从日期表中选择 DATEADD(dd, 0, DATEDIFF(dd, 0, MyDate))

  |--Compute Scalar(DEFINE:([Expr1004]=dateadd(day,(0),CONVERT_IMPLICIT(datetime,datediff(day,'1900-01-01 00:00:00.000',CONVERT_IMPLICIT(datetime,[TEST].[dbo].[DatesTable].[MyDate],0)),0))))
       |--Table Scan(OBJECT:([TEST].[dbo].[DatesTable]))

像@digi 建议的那样使用 FLOOR() 具有更接近 DateDiff 的性能,但不建议将 DateTime 数据类型转换为 float 和 back 并不总是产生原始值。

记住伙计们:不要相信任何人。查看性能统计数据,并自行测试!

测试结果时要小心。向客户端选择许多行将隐藏性能差异,因为通过网络发送行所需的时间比执行计算所需的时间长。因此,请确保所有行的工作都由服务器完成,但没有发送到客户端的行集。

有些人似乎对缓存优化何时影响查询感到困惑。在同一批次或不同批次中运行两个查询对缓存没有影响。因此,您可以手动使缓存过期,也可以简单地多次来回运行查询。查询 #2 的任何优化也会影响任何后续查询,因此如果您愿意,请放弃执行 #1。

这是证明 DateDiff 比转换为 varchar 快得多的 full test script and performance results


Ricardo C,很好的调查!您使用什么版本的 SQL Server?在 MSSQL2000 上,使用 datediff 的方法对我来说执行得稍微快一些。
请注意,我进行了 1000.000 次测试。对于现实世界的场景,性能差异不会很明显,我猜
Aku,我在这个测试中使用了 SQL Server 2005 Express。我在工作中使用 2000,我将使用一个包含超过 2400 万行的表来测试它,看看它会产生什么结果。
阿库,同样的结果。超过一千万行的性能没有差异。
关于同等性能的说法是不正确的。当然执行计划是一样的!!!必须通过比较 CPU 使用率而不是检查执行计划来测量这些性能。
V
Vladimir Vagaytsev

尝试这个:

SELECT CONVERT(VARCHAR(10),GETDATE(),111)

以上语句将您当前的格式转换为YYYY/MM/DD,请参考this link选择您喜欢的格式。


这将为我返回“2008/09/22”
SELECT CONVERT(VARCHAR(10),GETDATE(),101) 是 mm/dd/yyyy 格式。
如果您根据原始文本值(在数据库之外)进行排序,那么“日语”格式会更好
a
abatishchev
SELECT CONVERT(datetime, CONVERT(varchar, GETDATE(), 101))

M
Mahesh ML

以日期格式返回

CAST(OrderDate AS 日期)

上面的代码将在 sql server 2010 中工作

它将在 2013 年 12 月 12 日返回

对于 SQL Server 2012,请使用以下代码

CONVERT(VARCHAR(10), OrderDate , 111)

这会返回零时间的日期,而不仅仅是日期
如果您使用的是sql server,我可以知道哪个版本吗?
@MaheshML 它在 MS SQL 2012 中返回日期和时间。
在 SQL Azure 中像魅力一样工作
@MaheshML 没有 SQL Server 2010 这样的东西。
u
ughai

您可以使用 CONVERT 函数仅返回日期。请参阅以下链接:

Date and Time Manipulation in SQL Server 2000

CAST and CONVERT

使用转换函数的语法是:

CONVERT ( data_type [ ( length ) ] , expression [ , style ] ) 

M
Michael

如果您需要将结果作为 varchar,您应该通过

SELECT CONVERT(DATE, GETDATE()) --2014-03-26
SELECT CONVERT(VARCHAR(10), GETDATE(), 111) --2014/03/26

上面已经提到过。

如果您需要日期和时间格式的结果,您应该使用以下任何查询

SELECT CONVERT(DATETIME, CONVERT(VARCHAR(10), GETDATE(), 111)) AS OnlyDate 2014-03-26 00:00:00.000 SELECT CONVERT(DATETIME, CONVERT(VARCHAR(10), GETDATE(), 112)) AS OnlyDate 2014-03-26 00:00:00.000 DECLARE @OnlyDate DATETIME SET @OnlyDate = DATEDIFF(DD, 0, GETDATE()) 选择 @OnlyDate AS OnlyDate 2014-03-26 00:00:00.000


S
Somnath Muluk

如果您使用的是 SQL Server 2012 或更高版本,

使用 Format() 函数。

SQL Server 已经有多种答案和格式类型。但是大多数方法都有些模棱两可,您很难记住与特定日期格式相关的格式类型或函数的数字。这就是为什么在 SQL Server 的下一个版本中有更好的选择。

FORMAT ( value, format [, culture ] )

文化选项非常有用,因为您可以根据观众指定日期。

您必须记住 d(用于小图案)和 D(用于长图案)。

1."d" - 短日期模式。

2009-06-15T13:45:30 -> 6/15/2009 (en-US)
2009-06-15T13:45:30 -> 15/06/2009 (fr-FR)
2009-06-15T13:45:30 -> 2009/06/15 (ja-JP)

2.“D” - 长日期模式。

2009-06-15T13:45:30 -> Monday, June 15, 2009 (en-US)
2009-06-15T13:45:30 -> 15 июня 2009 г. (ru-RU)
2009-06-15T13:45:30 -> Montag, 15. Juni 2009 (de-DE)

查询中的更多示例。

DECLARE @d DATETIME = '10/01/2011';
SELECT FORMAT ( @d, 'd', 'en-US' ) AS 'US English Result'
      ,FORMAT ( @d, 'd', 'en-gb' ) AS 'Great Britain English Result'
      ,FORMAT ( @d, 'd', 'de-de' ) AS 'German Result'
      ,FORMAT ( @d, 'd', 'zh-cn' ) AS 'Simplified Chinese (PRC) Result'; 

SELECT FORMAT ( @d, 'D', 'en-US' ) AS 'US English Result'
      ,FORMAT ( @d, 'D', 'en-gb' ) AS 'Great Britain English Result'
      ,FORMAT ( @d, 'D', 'de-de' ) AS 'German Result'
      ,FORMAT ( @d, 'D', 'zh-cn' ) AS 'Chinese (Simplified PRC) Result';

US English Result Great Britain English Result  German Result Simplified Chinese (PRC) Result
----------------  ----------------------------- ------------- -------------------------------------
10/1/2011         01/10/2011                    01.10.2011    2011/10/1

US English Result            Great Britain English Result  German Result                    Chinese (Simplified PRC) Result
---------------------------- ----------------------------- -----------------------------  ---------------------------------------
Saturday, October 01, 2011   01 October 2011               Samstag, 1. Oktober 2011        2011年10月1日

如果你想要更多的格式,你可以去:

标准日期和时间格式字符串 自定义日期和时间格式字符串


要跳过文化,自定义格式允许您设置自己的格式,例如 FORMAT (@d, 'yyyyy-MM-dd') 以获取 2011-10-11。
无论如何,在 SQL Server 中使用 FORMAT 至少比您能想到的一些最疯狂的转换慢 20 倍。我会远离它的一切。
J
John Sonnino

做就是了:

SELECT CAST(date_variable AS date)

或与 PostgreSQL 一起使用:

SELECT date_variable::date

这称为类型转换顺便说一句!


D
DiGi

使用 FLOOR() - 只是减少时间部分。

SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)

这种方法不是最快的,并且还含蓄地告诉人们将日期转换为浮点数是准确的,但事实并非如此。有关详细信息,请参阅 this post
M
MDM
SELECT CONVERT(VARCHAR,DATEADD(DAY,-1,GETDATE()),103) --21/09/2011

SELECT CONVERT(VARCHAR,DATEADD(DAY,-1,GETDATE()),101) --09/21/2011

SELECT CONVERT(VARCHAR,DATEADD(DAY,-1,GETDATE()),111) --2011/09/21

SELECT CONVERT(VARCHAR,DATEADD(DAY,-1,GETDATE()),107) --Sep 21, 2011

F
Focusyn

如果您想使用 CONVERT 并获得与提出的原始问题相同的输出,即 yyyy-mm-dd 然后使用 CONVERT(varchar(10),[SourceDate as dateTime],121) 与前几个答案相同的代码,但转换为 yyyy-mm-dd 的代码破折号是 121。

如果我能在我的肥皂盒上稍等片刻,这种格式不属于数据层,这就是为什么在 SQL Server 2008 之前没有愚蠢的高开销“技巧”是不可能的,当时实际的 datepart 数据类型是介绍了。在数据层进行这样的转换是对 DBMS 开销的巨大浪费,但更重要的是,当您执行此类操作时,您基本上已经创建了内存中的孤立数据,我假设您将返回到程序中。您不能将其放回另一个 3NF+ 列或将其与键入的任何内容进行比较而无需还原,因此您所做的只是引入了故障点并删除了关系引用。

您应该始终将您的 dateTime 数据类型返回给调用程序,并在 PRESENTATION 层中进行必要的调整。一旦你在将它们返回给调用者之前进行转换,你就消除了应用程序中引用完整性的所有希望。这将再次阻止 UPDATE 或 DELETE 操作,除非您进行某种手动还原,否则在不需要时再次将您的数据暴露给人/代码/gremlin 错误。


除非您想要一个查询来检索与用户提供的日期匹配的所有记录作为某个时间字段的日期部分。祝你好运,只在表示层这样做。 (你不需要转换,你可以使用日期算术,但你明白了……)
@Andrew 为什么这很重要?您说 WHERE col >= @Date AND col < DATEADD(DAY, 1, @Date); - 绝对没有理由从列中删除时间。
@AaronBertrand 仅在输入 @Date 的时间部分为零的情况下才有效。如果这不是真的,您仍然需要知道如何在服务器端截断时间。我同意这个答案,即格式应该留给表示层,但我不同意将它留给前端意味着您不必知道截断的快速方法的暗示。
@Andrew您所要做的就是使输入参数DATE。我的观点仍然是,您永远不必对列应用任何此类截断,即使这是大多数人的第一直觉。
@AaronBertrand 并假设您可以控制参数的数据类型。在存储过程中很好,在其他情况下不太可能。为什么不强制转换以确保参数是您想要和需要的类型?
c
chancrovsky
SELECT DATEADD(DD, DATEDIFF(DD, 0, GETDATE()), 0)

SELECT DATEADD(DAY, 0, DATEDIFF(DAY,0, GETDATE()))

SELECT CONVERT(DATETIME, CONVERT(VARCHAR(10), GETDATE(), 101))

编辑:前两种方法基本相同,并执行转换为 varchar 方法。


这些方法都很棒,但是您建议使用哪一种?
请注意,前两个的“正确”版本是 select dateadd(dd, datediff(dd, 0, getdate()), 0),因为 dd 然后可以替换为 the datepart keywords 中的任何一个,以便在您选择的任何段中剪辑日期。 (另请注意,dd 只是 day 的缩写。)
c
chancrovsky

为了获得指示的结果,我使用以下命令。

SELECT CONVERT(DATETIME,CONVERT(DATE,GETDATE()))

我希望它很有用。


A
Art Schmidt

如果要将结果分配给列或变量,请为其指定 DATE 类型,并且转换是隐式的。

DECLARE @Date DATE = GETDATE()   

SELECT @Date   --> 2017-05-03

I
Imran Ali Khan
 Convert(nvarchar(10), getdate(), 101) --->  5/12/14

 Convert(nvarchar(12), getdate(), 101) --->  5/12/2014

K
Kris Khairallah

日期:

SELECT CONVERT(date, GETDATE())
SELECT CAST(GETDATE() as date)

时间:

SELECT CONVERT(time , GETDATE() , 114)
SELECT CAST(GETDATE() as time)

R
Radim Köhler

我认为这适用于您的情况:

CONVERT(VARCHAR(10),Person.DateOfBirth,111) AS BirthDate
//here date is obtained as 1990/09/25

c
chancrovsky
DECLARE @yourdate DATETIME = '11/1/2014 12:25pm'    
SELECT CONVERT(DATE, @yourdate)

此建议已被其他答案(不止一次)涵盖。
K
Krishnraj Rana

好的,虽然我有点晚了:),这是另一个解决方案。

SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) as DATETIME)

结果

2008-09-22 00:00:00.000

如果您使用的是 SQL Server 2012 及更高版本,那么您可以像这样使用 FORMAT() 函数 -

SELECT FORMAT(GETDATE(), 'yyyy-MM-dd')

您的第一个示例仍然有一个时间组件。问题的关键是如何删除它。
E
Eric Aya

只需您可以这样做:

SELECT CONVERT(date, getdate())
SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, @your_date))
SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))

输出为:

2008-09-22 00:00:00.000

或者干脆这样做:

SELECT CONVERT (DATE, GETDATE()) 'Date Part Only'

结果:

Date Part Only
--------------
2013-07-14

M
Mohammad Neamul Islam

在这种情况下,仅日期,我们将运行此查询:

https://i.stack.imgur.com/DDheQ.png


t
tumultous_rooster

即使使用古老的 MSSQL Server 7.0,此处的代码(由 link 提供)也允许我获得当时我正在寻找的任何日期格式:

PRINT '1) Date/time in format MON DD YYYY HH:MI AM (OR PM): ' + CONVERT(CHAR(19),GETDATE())  
PRINT '2) Date/time in format MM-DD-YY: ' + CONVERT(CHAR(8),GETDATE(),10)  
PRINT '3) Date/time in format MM-DD-YYYY: ' + CONVERT(CHAR(10),GETDATE(),110) 
PRINT '4) Date/time in format DD MON YYYY: ' + CONVERT(CHAR(11),GETDATE(),106)
PRINT '5) Date/time in format DD MON YY: ' + CONVERT(CHAR(9),GETDATE(),6) 
PRINT '6) Date/time in format DD MON YYYY HH:MM:SS:MMM(24H): ' + CONVERT(CHAR(24),GETDATE(),113)

它产生了这个输出:

1) Date/time in format MON DD YYYY HH:MI AM (OR PM): Feb 27 2015  1:14PM
2) Date/time in format MM-DD-YY: 02-27-15
3) Date/time in format MM-DD-YYYY: 02-27-2015
4) Date/time in format DD MON YYYY: 27 Feb 2015
5) Date/time in format DD MON YY: 27 Feb 15
6) Date/time in format DD MON YYYY HH:MM:SS:MMM(24H): 27 Feb 2015 13:14:46:630

x
xbb

从 SQL SERVER 2012 开始,您可以这样做:

SELECT FORMAT(GETDATE(), 'yyyy-MM-dd 00:00:00.000')


J
Janaka R Rajapaksha

你为什么不使用 DATE_FORMAT(your_datetiem_column, '%d-%m-%Y') ?

例如:select DATE_FORMAT( some_datetime_column, '%d-%m-%Y' ) from table_name

您可以通过重新排列 '%d-%m-%Y' 部分来更改 m、d 和 year 的顺序


l
lit

我知道这是旧的,但我没有看到有人这样说。据我所知,这是 ANSI 标准。

SELECT CAST(CURRENT_TIMESTAMP AS DATE)

如果 Microsoft 也可以支持 ANSI 标准 CURRENT_DATE 变量,那就太好了。


select {fn current_date()} as today 适合我。
@brianary - 很好,但它不是 ANSI SQL。
这很公平,你的答案很好移植,但我认为只要我们在 T-SQL 周围工作,这也有效(并表明实现 ANSI CURRENT_DATE 对 MS 来说是微不足道的)。
c
chancrovsky

我赞成以下未提及的内容:

DATEFROMPARTS(DATEPART(yyyy, @mydatetime), DATEPART(mm, @mydatetime), DATEPART(dd, @mydatetime))

它也不关心本地或进行双重转换——尽管每个“日期部分”可能都会做数学运算。所以它可能比 datediff 方法慢一点,但对我来说它更清楚。特别是当我只想按年和月分组时(将日期设置为 1)。


J
Jonathan Leffler

在 SQL Server 2000 上

CAST(
(
    STR( YEAR( GETDATE() ) ) + '/' +
    STR( MONTH( GETDATE() ) ) + '/' +
    STR( DAY( GETDATE() ) )
)
AS DATETIME)