(如果它是int 列,请阅读下面的答案)
假设它是一个文本字符串:
假设datadate 是一个字符串(字符、文本等)列而不是date/datetime/datetime2/datetimeoffset 列,则将CONVERT 函数与style: 23 一起使用. 23 值对应于 ISO 8601,因为这些值按 yyyy-MM-dd 顺序排列,即使它们缺少破折号。
此页面有style编号的引用:https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver15
SELECT
*
FROM
(
SELECT
myTable.*
CONVERT( date, datadate, 23 ) AS valueAsDate
FROM
myTable
) AS q
WHERE
q.valueAsDate = DATEADD( dd, -1, GETDATE() )
假设它是一个实际的int 列:
快速而简单的方法是将int 转换为varchar,然后使用与上面相同的代码,就好像它是一个文本字段一样 - 但不要这样做因为它很慢:
SELECT
*
FROM
(
SELECT
myTable.*,
CONVERT( char(8), datadate ) AS valueAsChar,
CONVERT( date, CONVERT( char(8), datadate ), 23 ) AS valueAsDate
FROM
myTable
) AS q
WHERE
q.valueAsDate = DATEADD( dd, -1, GETDATE() )
假设它是一个实际的 int 列(更好的答案):
我们需要使用 DATEFROMPARTS 并使用 Base-10 算法提取每个组件 (fun)!
如果我们有一个表示格式化日期的整数(恐怖),例如20200531,那么:
- 我们可以通过执行
MOD 31(例如19950707 MOD 31 == 7)来获得这一天
- 我们可以先除以100去掉日部分,然后
MOD 12:(例如20200531 / 100 == 202005,202005 MOD 12 == 5)得到月份
- 我们可以通过除以
10,000 得到年份(例如20200531 / 10000 == 2020)。
顺便说一句:
- SQL Server 使用
% 代替 MOD 作为模运算符。
- 整数除法会导致截断,而不是产生十进制或浮点值(例如
5 / 2 == 2 而不是 2.5)。
像这样:
SELECT
q2.*
FROM
(
SELECT
q.*,
DATEFROMPARTS( q.[Year], q.MonthOfYear, q.DayOfMonth ) AS valueAsDate
FROM
(
SELECT
myTable.*,
( datadate % 31 ) AS DayOfMonth,
( ( datadate / 100 ) % 12 ) AS MonthOfYear,
( datadate / 10000 ) AS [Year]
FROM
myTable
) AS q
) AS q2
WHERE
q2.valueAsDate = DATEADD( dd, -1, GETDATE() )
显然,使用两个嵌套子查询是一件很痛苦的事情 (SQL 的人机工程学很糟糕,我不明白 SQL 如何或为什么不允许 SELECT 子句中的表达式被其他表达式使用在同一个查询中 - 人体工程学真的很糟糕......) - 但我们可以将其转换为标量 UDF(和SQL Server will inline scalar UDFs,因此不会影响性能)。
此函数中有一个 TRY/CATCH 块,因为您可能会处理像 20209900 这样的无效值(这不是真实日期,因为 2020 年没有第 99 个月和第 0 天) .在这种情况下,函数返回NULL。
CREATE FUNCTION dbo.convertHorribleIntegerDate( @value int ) RETURNS date AS
BEGIN
DECLARE @dayOfMonth int = @value % 31;
DECLARE @monthOfYear int = ( @value / 100 ) % 100;
DECLARE @year int = @value / 10000;
BEGIN TRY
RETURN DATEFROMPARTS( @dayOfMonth, @monthOfYear, @year );
END TRY;
BEGIN CATCH
RETURN NULL;
END CATCH;
END
我们可以在这样的查询中使用:
SELECT
myTable.*,
dbo.convertHorribleIntegerDate( datadate ) AS valueAsDate
FROM
myTable
由于SELECT 无法与同一查询中的其他表达式共享表达式结果,您仍然需要使用外部查询来处理valueAsDate(或重复dbo.convertHorribleIntegerDate 函数调用):
SELECT
*
FROM
(
SELECT
myTable.*,
dbo.convertHorribleIntegerDate( datadate ) AS valueAsDate
FROM
myTable
) AS q
WHERE
q.valueAsDate = DATEADD( dd, -1, GETDATE() )