将 MS Access 查询(使用 IIF() 和 DATESERIAL())事务处理到 T-SQL

Posted

技术标签:

【中文标题】将 MS Access 查询(使用 IIF() 和 DATESERIAL())事务处理到 T-SQL【英文标题】:Transacting MS Access query (using IIF() and DATESERIAL()) into T-SQL 【发布时间】:2015-10-02 08:30:44 【问题描述】:

我正在尝试将一些 MS Access 查询转换为 T-SQL 以在 SSIS 中使用(基本上将 Access db 转换为 SQL Server 2008),但我在转换 IIF() 语句时遇到了问题。我尝试了几种方法,但总是导致错误。

查询创建一个列,其日期为“如果满足条件,则为原始日期 + 2 年,如果不满足条件,则为原始日期 + 1”。 IIF() 的第一部分消除了原始年份是闰年的情况,从而消除了生成不存在日期的可能性。

原来的IIF()语句是:

IIf((Day(Date)=29 And Month(Date)=2),   
IIf(Desc Like "*" & "123" & "*",
    DateSerial(Year(Date)+2,Month(Date),Day(Date)-1),
    DateSerial(Year(Date)+1,Month(Date),Day(Date)-1)),  
IIf(Desc Like "*" & "123" & "*",
    DateSerial(Year(Date)+2,Month(Date),Day(Date)),
    DateSerial(Year(Date)+1,Month(Date),Day(Date)))) AS Term

所以问题不仅在于 IIF() 语句,还在于 DATESERIAL 函数。我找到了使用 CAST() 的 DATESERIAL() 函数的解决方案(SQL server 2008 没有 DATEFROMPARTS() 函数...)。

我尝试像这样使用 CASE():

CASE
WHEN DAY(Date)=29 AND Month(Date)=2 THEN
    CASE
        WHEN Desc LIKE "%123%" THEN
    CAST(CAST(YEAR(Date)+2 AS VARCHAR(4)) + RIGHT('0' + CAST(MONTH(Date) AS VARCHAR(2)), 2) + RIGHT('0' + CAST(DAY(Date)-1 AS VARCHAR(2)), 2) AS DATETIME )
        ELSE CAST(CAST(YEAR(Date)+1 AS VARCHAR(4)) + RIGHT('0' + CAST(MONTH(Date) AS VARCHAR(2)), 2) + RIGHT('0' + CAST(DAY(Date)-1 AS VARCHAR(2)), 2) AS DATETIME ) END

ELSE CASE
    WHEN Desc LIKE "%123%" THEN
    THEN CAST(CAST(YEAR(Date)+2 AS VARCHAR(4)) + RIGHT('0' + CAST(MONTH(Date) AS VARCHAR(2)), 2) + RIGHT('0' + CAST(DAY(Date) AS VARCHAR(2)), 2) AS DATETIME )
    ELSE CAST(CAST(YEAR(Date)+1 AS VARCHAR(4)) + RIGHT('0' + CAST(MONTH(Date) AS VARCHAR(2)), 2) + RIGHT('0' + CAST(DAY(Date) AS VARCHAR(2)), 2) AS DATETIME )END END AS Term

我也尝试过使用 COAELSCE(),但没有更好的结果。

我真的不知道我是否犯了某种语法错误或问题可能出在哪里。

提前感谢您的帮助。

编辑:我将添加我收到的错误消息:'...' 附近的语法不正确。当我尝试不同的方法时,“...”会发生变化,有时是 ELSE、THEN 等。

【问题讨论】:

您可能知道这一点,但 Desc LIKE "123" 应该是 Desc LIKE "%123%" 以对应于您的 Access 查询。 是的,对不起,这只是一个错字。我会编辑它。 您能否描述正在发生的事情(例如错误消息/错误结果)以及这与您的预期有何不同? 我总是收到一个错误,上面写着“ELSE/THEN 附近的语法不正确......”,我可能在帖子中提到过......我试图在语法中找到一个错误,但确实没有发现任何东西。 在最后的 ELSE CASE 中有两个 THEN 并排,但我认为有更简单的方法可以做到这一点,请参阅我的答案...... 【参考方案1】:

SQL Server 的 DATEADD 可能有助于简化这里的事情...

 CASE WHEN (<your condition>) 
 THEN DATEADD(YEAR, 1, [OriginalDate]) 
 ELSE DATEADD(YEAR, 2, [OriginalDate])
 END

也应该应对闰年。

【讨论】:

谢谢,看来这工作得很好。我简直不敢相信这是多么简单,我花了半天时间处理我的 20 行代码......【参考方案2】:

DateSerial 是一个非常有用的函数,只需创建您自己的即可。 我从here 得到我的版本:

CREATE FUNCTION dbo.DateSerial
(
  @year int,
  @month int,
  @day int
)
RETURNS datetime
AS
BEGIN
   DECLARE @date datetime

   -- convert date by adding together like yyyymmdd
   SET @date = cast(@year * 10000 + 101 AS char(8));

   -- Add to date the proper months subtracting 1, since we used 1 as start instead of zero.    
   SET @date = dateadd(mm , @month - 1 , @date)
   -- Add to date the proper days subtracting 1, since we used 1 as start instead of zero.    
   SET @date = dateadd(dd , @day - 1 , @date);

   RETURN @date ;
END;
GO

这是另一种方式:Date serial in SQL?

然后像在 Access 中一样使用该函数。

编辑:刚刚注意到您的外部 IIF 用于处理闰年。使用dateadd() 时不需要。

【讨论】:

以上是关于将 MS Access 查询(使用 IIF() 和 DATESERIAL())事务处理到 T-SQL的主要内容,如果未能解决你的问题,请参考以下文章

iif 日期超过两次 MS-Access [关闭]

MS Access 查询条件 IIf true then <

查询在 iif ms-access sql 中不返回真值

Sum() 使用 IIF() 或 MS Access 中的 Where 子句

MS Access 查询转换为 Sql Server

MS ACCESS 2016 - 使用 Null 进行查询的标准