与INNER JOIN

时间:2016-03-11 20:22:14

标签: sql-server

我有以下查询:

SELECT
T2.PseudoDateColumn
FROM
    (
    SELECT
    *
    FROM T1
    WHERE
    PseudoDateColumn <> -1
    ) T2
INNER JOIN T3
    ON T2.T2_key = T3.T3_key  
WHERE
CAST(CAST(T2.PseudoDateColumn AS VARCHAR) AS DATE) 
BETWEEN 
DATEADD(mm, -1, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)) 
AND DATEADD(ms, -3, DATEADD(mm, 0, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)))

PseudoDateColumnint中的T1。非实际日期的值具有-1占位符。所有其他日期都是实际日期(仅存储为int)。因此,在将-1投射到PseudoDateColumn之前,我需要首先过滤掉所有DATE值,以便我可以使用BETWEEN。当我在没有join的情况下运行此脚本时,它可以正常工作。但是,当我使用join运行它时,SQL会抛出错误:

  

“从字符转换日期和/或时间时转换失败   字符串“

我不知道为什么会这样。就像SQL在子查询之前进行CASTing一样。

更新: 我错误地写了SQL Server 2008.我实际上是在 PDW AU5 上运行它,它有SQL Server 2012.但我不认为这会产生影响。

此外,以下是PseudoDateColumn中的一些示例数据。所有值均采用YYYYMMDD形式。

PseudoDateColumn
-----------------
20150112
20160305
20111009

2 个答案:

答案 0 :(得分:0)

行为的最可能解释是存储在PseudoDateColumn中的“坏”值。但是你应该可以调试它。

当SQL Server具有一个非常适合DATE数据类型的自定义设计用于存储日期值时,将“日期”值存储在整数列中似乎是一种反模式。

但是,如果您需要使用已有的内容,并在不改变架构定义的情况下解决问题......

SQL Server有一个ISDATE函数,您可以使用test test测试字符串的有效性。不幸的是,ISDATE执行的检查并不像实际的CAST那样严格,但它确实捕获了最令人震惊的“坏”值。

我的建议:

而不是将整数转换为日期(存储在列中的整数值...

将您的文字DATE值转换/转换为整数,转换为与列(整数)相同的数据类型/格式,并与原始整数列进行比较。

所以你的查询会是这样的:

WHERE T2.PseudoDateColumn >= CONVERT(INT, CONVERT(VARCHAR(8), datexpr1, 112) )
  AND T2.PseudoDateColumn <  CONVERT(INT, CONVERT(VARCHAR(8), datexpr2, 112) ) 

在该示例中, dateexpr1 dateexpr2 将替换为返回DATE数据类型的表达式,如表达式在原始查询中。

注意:这种类型的范围比较取决于存储的整数值是规范的。 (以年份为先(四位数),然后是月份(两位数),然后是一天(两位数)。在该表示中,我们保证比较

 (int)a  <= (int)b  < (int)c

将产生与

相同的结果
 (date)a <= (date)b < (date)c

(除了因“无法”转换为有效日期的“坏”整数值而产生的差异...例如,具有无效“月”和/或“日”部分的整数值,例如{ {1}}(月份为13,日期为零)

一个整数比较检查2016年的伪数据将“正常”,而不会抛出错误......

20161300

这种方法完全避免了尝试将“坏”伪造的整数值转换为20160101 <= 20161300 < 2017000 -> TRUE 的问题。但始终可以将有效的DATE转换为DATE格式的整数。

作为此模式的一个额外好处,使用裸YYYYMMDD列上的谓词,SQL Server可能能够有效地使用以PseudoDateColumn作为前导列的索引。

如果您在将PseudoDateColumn转换为DATE时设置为死,则可以先使用PseudoDateColumn函数执行验证值的条件测试。像这样:

ISDATE

答案 1 :(得分:0)

我知道这是一篇旧文章,但我认为这可以对某人有所帮助。尝试在内部联接中将VARCHAR输入参数转换/广播到UNIQUEIDENTIFIER时遇到类似的错误。我的所有数据都是有效的,并且如果在联接之外完成转换,则转换效果很好,但是在联接期间 会失败。实际上,我什至在SQL Server Management Studio的结果窗格中都得到了结果,但是仍然抛出该错误。对我有用的是使用TRY_CASTTRY_CONVERT而不是CASTCONVERT。我友善的邻里DBA建议使用此解决方案,因为它可以确保及早执行或类似的方法。