我有一个Datetime2格式的日期,它显示为yyyy-mm-dd。有没有办法重新格式化它,所以它是mm-dd-yyyy?
CASE
WHEN CAST(ai.[Due Date] AS DATETIME2) < GETDATE() THEN '[due]' + LEFT((ai.[Due Date]),10)
WHEN CAST(ai.[Due Date] AS DATETIME2) IS NULL THEN ' '
ELSE LEFT((ai.[Due Date]),10)
END AS [TD]
答案 0 :(得分:4)
传统方式是使用convert()
:
convert(varchar(10), ai.[Due Date], 110)
更通用的方法使用format()
:
select format(ai.[Due Date], 'dd-MM-yyyy')
答案 1 :(得分:3)
您误解了日期值如何在数据库中工作。 没有人类可读的格式。当您看到DateTime
或DateTime2
格式为yyyy-mm-dd
的值时,您看到的是调试器或查询工具为方便起见显示的内容;数据库中使用的实际值是二进制的,而不是人类可读的,旨在有效地进行存储,索引和日期算术。
如果需要查看特定格式的值,则必须将其convert()
或format()
设为varchar
系列中的类型,作为查询的一部分。或者,甚至更好的是,让您的应用程序代码/报告工具为您完成此操作,然后只返回原始值。
我还看到这些日期可能最初存储在varchar
或nvarchar
列中。如果是这样,这是架构设计中的一个主要缺陷。如果您可以开始使用以下方式存储这些值,那么您将获得显着的性能优势,并省去了很多麻烦。首先是DateTime
系列的一种类型。
考虑到这一点,并且由于不清楚您是从什么开始的,所以让我们按喜好顺序看五个场景:
DateTime
系列中的类型,您可以让您的应用程序/报告工具处理该格式在架构中使用真实的DateTime值对您有好处。这就是我们期望看到的。甚至更好的是,突然之间,您的SQL中的所有事情都变得真正变得简单了,问题中的整个代码片段都简化为:
ai.[Due Date] AS [TD]
DateTime
系列的类型,但是客户端系统无法格式化这还是相当不错的。模式仍然可以,在这种情况下,我们仍然可以对原始代码进行一些简化:
COALESCE(
CASE WHEN ai.[Due Date] < GETDATE() THEN '[due] ' ELSE '' END
+ FORMAT(ai.[Due Date], 'MM-dd-yyyy')
, ' ') AS [TD]
varchar
系列中的a类型,但是您可以将其修复为使用DateTime2
我在这里说“修复”,因为现在该架构实际上是 broken 。但这没关系:您可以修复它。 这样做。然后使用上一个场景中的代码。
varchar
系列的类型,您无法修复,但至少原始数据始终使用语义'yyyy-MM-dd`格式笨蛋。您陷入了一个破碎的模式。但是我们至少可以利用格式良好的数据,通过对get_date()
表达式使用强制转换/转换来匹配列,从而使事情 很多 更高效,而不是现在相反,就像这样:
WHEN ai.[Due Date] < CONVERT(varchar, GETDATE(), 120)
现在,我们正在进行字符串比较而不是日期比较,这通常比较慢,而且很容易出错。但是由于数据格式优美,我们可以避免这种情况,节省的余地是我们只需要强制转换一个get_date()
值,而不是我们拥有的每一行。而且,以这种方式,列上的任何索引仍然有效。该问题的代码段将无法使用[Due Date]
列上的任何索引。我知道这是一个SELECT
子句,但这对于一般情况是值得记住的。
此方案的完整解决方案现在看起来像这样:
COALESCE(
CASE WHEN ai.[Due Date] < CONVERT(varchar, GETDATE(), 120) THEN '[due] ' ELSE '' END
+ FORMAT(CAST(ai.[Due Date]) AS Date), 'MM-dd-yyyy')
, ' ') AS [TD]
同样,如果您无法将原始列数据转换为DateTime
格式,请仅执行此操作。这就是您真正想要的。
varchar
族中的一种类型,您无法修复,且格式不语义或不一致哦,男孩。这是您真正不想要的地方。如果您无能为力,请至少 查看是否可以开始将一致的语义值添加到列中。在这一点上,我们不得不为几乎每一个查询对每行(可能不止一次)进行额外的工作。我们开始:
COALESCE(
CASE WHEN CAST(ai.[Due Date] AS DATETIME2) < GETDATE() THEN '[due] ' ELSE '' END
+ FORMAT(CAST(ai.[Due Date] AS DATETIME2), 'MM-dd-yyyy')
, ' ') AS [TD]
代码看起来与其他选项没有太大不同,但是性能特征将完全不同……可能会恶化多个数量级。
请记住:由于国际化和时区问题,字符串和日期之间的转换出奇的缓慢和昂贵。避免在所有查询中都这样做。