施法给了我错误的约会?

时间:2012-07-07 13:32:02

标签: sql-server casting

SELECT DATEPART(YEAR, PURCHASE_DATE) AS TRANSACTION_YEAR, DATEPART(MONTH, PURCHASE_DATE) AS TRANSACTION_MONTH,
CASE WHEN DATEPART(YEAR, DUE_DATE) >= DATEPART(YEAR, PURCHASE_DATE) THEN DATEPART(YEAR, DUE_DATE)
ELSE DATEPART(YEAR, PURCHASE_DATE) END AS RELEASE_YEAR, 
CASE WHEN (DATEPART(YEAR, DUE_DATE) = DATEPART(YEAR, PURCHASE_DATE) AND DATEPART(MONTH, DUE_DATE) >= DATEPART(MONTH, PURCHASE_DATE)) THEN DATEPART(MONTH, DUE_DATE)
WHEN DATEPART(YEAR, DUE_DATE) > DATEPART(YEAR, PURCHASE_DATE) THEN DATEPART(MONTH, DUE_DATE)
ELSE
DATEPART(MONTH, PURCHASE_DATE) END AS RELEASE_MONTH,
CAST(YEAR(CASE WHEN DATEPART(YEAR, DUE_DATE) >= DATEPART(YEAR, PURCHASE_DATE) THEN DATEPART(YEAR, DUE_DATE)
ELSE DATEPART(YEAR, PURCHASE_DATE) END) AS VARCHAR(4)) + RIGHT('0'+CAST(MONTH(CASE WHEN (DATEPART(YEAR, DUE_DATE) = DATEPART(YEAR, PURCHASE_DATE) AND DATEPART(MONTH, DUE_DATE) >= DATEPART(MONTH, PURCHASE_DATE)) THEN DATEPART(MONTH, DUE_DATE)
WHEN DATEPART(YEAR, DUE_DATE) > DATEPART(YEAR, PURCHASE_DATE) THEN DATEPART(MONTH, DUE_DATE)
ELSE
DATEPART(MONTH, PURCHASE_DATE) END) AS VARCHAR(2)),2)
FROM TEST

在六个记录的样本表上生成

2012    1   2012    1   190501
2012    1   2013    12  190501
2011    1   2012    1   190501
2011    1   2011    1   190501
2012    1   2012    1   190501
2012    1   2012    2   190501

我做错了什么?

非常感谢!

2 个答案:

答案 0 :(得分:2)

我认为问题在于您已经使用CASE表达式提取月份和年份组件 - 并将这些表达式的结果传递给YEARMONTH函数 - 期望传递datetime值。因此,您正在将int隐式转换回datetime值。

SELECT YEAR(2012)

----
1905

SELECT MONTH(12)

----
01

int隐式转换为datetime时,它实际上是19000101后的天数。大多数日子〜19000101之后的2000天发生在1905年。


所有这一切都说,这看起来要比它需要的复杂得多 - 使用子查询,你可以执行一次适当的计算,而不是重复它们 - 初始输入是什么,最后输出你'瞄准?

答案 1 :(得分:0)

为什么你要一次性完成这一切并在整个地方重复自己。

如果你从

开始
select 
DatePart(YEAR,PURCHASE_DATE) as PURCHASE_YEAR,
DatePart(YEAR,DUE_DATE) as DUE_YEAR,
DatePart(MONTH,PURCHASE_DATE) as PURCHASE_MONTH,
DatePart(MONTH,DUE_DATE) as DUE_MONTH
From Test

然后你可以做

SELECT PURCHASE_Year AS TRANSACTION_YEAR, 
       PURCHASE_Month) AS TRANSACTION_MONTH,
       CASE 
       WHEN DUE_YEAR >= PURCHASE_YEAR THEN DUE_YEAR
       ELSE PURCHASE_YEAR
       END AS RELEASE_YEAR, 
       CASE 
       WHEN (DUE_YEAR = PURCHASE_YEAR) AND (DUE_MONTH >= PURCHASE_MONTH) THEN DUE_MONTH
       WHEN DUE_YEAR > PURCHASE_YEAR THEN DUE_MONTH
       ELSE PURCHASE_MONTH 
       END AS RELEASE_MONTH,
       CAST(
        CAST(RELEASE_YEAR As VarChar(4)) + 
        '-' + 
        CAST(RELEASE_MONTH as VarChar(2)) + 
        '-1' as DATE) as RELEASE_DATE
FROM (
select 
DatePart(YEAR,PURCHASE_DATE) as PURCHASE_YEAR,
DatePart(YEAR,DUE_DATE) as DUE_YEAR,
DatePart(MONTH,PURCHASE_DATE) as PURCHASE_MONTH,
DatePart(MONTH,DUE_DATE) as DUE_MONTH
From Test
) SomeDummyTableName

我认为这就是你所追求的目标,我甚至可能在趟过这条泥沼之后就把它弄好了。