将存储为VARCHAR的日期转换为INT,以与存储为INT的日期进行比较

时间:2015-10-10 00:38:26

标签: sql-server tsql type-conversion sql-server-2014

我正在使用SQL Server 2014.我相信我的要求相当简单。我有一个表包含一个字段,其中包含一个存储为VARCHAR的日期值,另一个表包含一个字段,其中包含一个存储为INT的日期值。

VARCHAR字段中的日期值存储如下: 2015M01
INT字段中的数据值存储如下: 201501

我需要使用EXCEPT将这些表格相互比较。我的思考过程是以某种方式从VARCHAR值中提取或修剪“M”,看看它是否会让我比较两者。如果有人有更好的想法,例如使用CAST来更改日期格式,或者可以随意提出建议。

我还担心即使从VARCHAR中提取“M”也可能会阻止比较,因为仍然会保留VARCHAR而另一个仍为INT。如果可能,通过T-SQL查询即时转换,这也是很好的建议。 :)

4 个答案:

答案 0 :(得分:2)

REPLACE 字符串,然后 CONVERT 更改为整数

SELECT A.*, B.*
FROM TableA A 
INNER JOIN 
   (SELECT intField 
    FROM TableB
   ) as  B
ON CONVERT(INT, REPLACE(A.varcharField, 'M', ''))  = B.intField

答案 1 :(得分:1)

如果您希望第一个表中的所有内容都不在第二个表中,您可能会考虑这样的事情:

select t1.*
from t1
where not exists (select 1
                  from t2
                  where cast(replace(t1.varcharfield, 'M', '') as int) = t2.intfield
                 );

为了您的目的,这应该足够接近except

我应该补充一点,您可能需要在where语句中包含其他列。但是,这个问题只提到了一个专栏,所以我不知道那些是什么。

答案 2 :(得分:1)

由于您说您已经拥有查询并且正在使用EXCEPT,因此您只需在包含VARCHAR值的查询中更改该“date”字段的定义,以使其与INT匹配{1}}其他查询的格式。例如:

SELECT Field1, CONVERT(INT, REPLACE(VarcharDateField, 'M', '')) AS [DateField], Field3
FROM   TableA
EXCEPT
SELECT Field1, IntDateField, Field3
FROM   TableB

但是,虽然我意识到这可能不可行,但如果你能做到这一点,你最好的选择就是改变表中VARCHAR字段的数据的存储方式,以便它是实际上是INT格式与表格相同,数据已存储为INT。那么你就不必担心像这样的情况。

含义:

  • 使用INT字段向表中添加VARCHAR字段。
  • 执行该表的UPDATE,将INT字段设置为删除了M的字符串值。
  • 更新外部服务(app,ETL等)使用的任何INSERT和/或UPDATE存储过程,以便在进入时执行相同的M删除逻辑。然后您不必更改任何应用程序代码INSERTs和UPDATEs。你甚至不需要告诉任何你这样做的人。
  • 更新外部服务(app,ETL等)使用的任何“get”/ SELECT存储过程以执行相反的逻辑:将INT转换为VARCHAR并添加M出去的路上。然后,您不必更改从数据库获取数据的任何应用程序代码。你甚至不需要告诉任何你这样做的人。

这是为您的数据库提供存储过程API非常方便的众多原因之一。我想ORM可以重建,但是你仍然需要重新编译,即使所有的代码引用都是自动更新的。但是使数据类型更改(甚至将字段移动到另一个表,甚至用简单的CASE语句替换一个字段)“在幕后”并屏蔽它,以便控制之外的任何代码都不会知道发生了变化,并不像大多数人想象的那么困难。我已经完成了所有这些操作(数据类型更改,将字段移动到不同的表,用简单的逻辑替换字段等等),它会花费你很多时间,直到应用程序代码可以更新。那可能是另一个处理这个问题的团队。也许他们的日程安排不允许在该区域进行任何更改(加上测试)3个月。好。它们准备就绪时会在那里等待它们。如果有几个区域要更新,那么它们可以一次完成一个。您甚至可以为任何更新的应用程序代码创建并行运行的新存储过程,以使正确的INT数据类型作为输入参数。一旦所有对VARCHAR值的引用都消失了,就删除这些存储过程的原始版本。

答案 3 :(得分:0)

您可以使用char列在表上创建持久化视图,并使用计算列删除M。然后,您可以JOIN查看包含INT列的表格。

CREATE VIEW dbo.PersistedView
WITH SCHEMA_BINDING
AS
SELECT ConvertedDateCol = CONVERT(INT, REPLACE(VarcharCol, 'M', ''))
    --, other columns including the PK, etc
FROM dbo.TablewithCharColumn;

CREATE CLUSTERED INDEX IX_PersistedView
ON dbo.PersistedView(<the PK column>);

SELECT *
FROM dbo.PersistedView pv
    INNER JOIN dbo.TableWithIntColumn ic ON pv.ConvertedDateCol = ic.IntDateCol;

如果您提供两个表的实际详细信息,我将编辑我的答案以使其更清晰。

与每次运行{SELECTCONVERT相比,加入两列的REPLACE语句中包含计算列的持久视图的效果会更好1}}陈述。

但是,持久化视图会略微减慢插入基础表的速度,并且会阻止您对基础表进行DDL更改。

如果您希望不通过模式绑定视图保留值,则可以在表本身上创建非持久计算列,然后在该列上创建非聚集索引。如果您使用SELECTWHERE条款中的计算列,您可能会看到一些好处。

举例来说:

JOIN

结果:

enter image description here