通过IF语句或CASE基于全局子串匹配更新表

时间:2012-01-11 08:38:31

标签: sql sql-server database date

我有数十万行,其中有四个日期列,这些行是按原样导入的:

Mon Nov 14 14:52:46 PST 2011
Fri Nov 04 07:50:21 PDT 2011
Thu Dec 01 00:00:00 PST 2011

有三个月:11月,12月,1月。我希望我的新日期格式以这种格式保存到新列:

  

11-14-2011,11-04-2011,12-01-2011等等......

我可以通过与子字符串月份名称匹配的更新语句来执行此操作,并将其替换为匹配的数字。所以我可以这样做:

UPDATE tabel 
   set col1 = REPLACE(substring(col2, 5,3) 'Nov', 11)

它适用于我跑的第一个月。但是当我然后添加Dec和Jan时,它只适用于那些月,并且在我刚才所有其他行中重置三个字母的字符串。

我不知道如何以正确的方式执行此UPDATE和REPLACE命令,因此它匹配数据库中的所有三个月,然后将新格式写入我想要的新列。我对T-SQL有点新意,到目前为止,我对那里的文档数量感到不知所措。我已经尝试将所有三个月放入一系列UPDATE语句中,但这些都没有用。我认为它需要逐行,测试一个条件然后执行更新,如果它匹配。

也许是这样的:

IF @dateColSubString = 'Jan' Then
   UPDATE table
         set newDateCol = REPLACE(substring(col2, 5,3) 'Jan', 01) + '-2012'
   COMMIT
IF @dateColSubString = 'Dec' Then
   UPDATE table
         set newDateCol = REPLACE(substring(col2, 5,3) 'Dec', 12) + '-2011'
   COMMIT

在新列'01 -2011'中创建这样的值,然后当我为'Nov'运行相同的更新请求然后'Dec'更改这些字符串时,不要将这些值重置为旧值。< / p>

我希望这是有道理的。

2 个答案:

答案 0 :(得分:3)

尝试此操作并使用日期时间执行任何操作

DECLARE @t TABLE(str varchar(100))
INSERT @t
VALUES('Mon Nov 14 14:52:46 PST 2011'),('Fri Nov 04 07:50:21 PDT 2011'),('Thu Dec 01 00:00:00 PST 2011')

SELECT 
    CAST(DATEPART(MONTH, CAST(SUBSTRING(str, 5, 6) +' '+RIGHT(str, 4) AS DATETIME)) AS VARCHAR) +'-'+ RIGHT(str, 4),
    CAST(SUBSTRING(str, 5, 6) +' '+RIGHT(str, 4) AS DATETIME),
    CONVERT(VARCHAR, CAST(SUBSTRING(str, 5, 6) +' '+RIGHT(str, 4) AS DATETIME), 110)
FROM @t

在你的情况下,假设,就像这样 - 你只需要选择哪个结果更适合你并采用相应的查询行:

SELECT 
    CAST(DATEPART(MONTH, CAST(SUBSTRING(order_send, 5, 6) +' '+RIGHT(order_send, 4) AS DATETIME)) AS VARCHAR) +'-'+ RIGHT(order_send, 4),
    CAST(SUBSTRING(order_send, 5, 6) +' '+RIGHT(order_send, 4) AS DATETIME),
    CONVERT(VARCHAR, CAST(SUBSTRING(order_send, 5, 6) +' '+RIGHT(order_send, 4) AS DATETIME), 110)
FROM YourTableName

答案 1 :(得分:2)

如果你没有丢失时区信息,你可以简单地删除星期几和时区部分,并使用简单的datetimeCAST将结果字符串转换为CONVERT,像这样:

;
WITH StringDates (OldDateCol) AS (
  SELECT 'Mon Nov 14 14:52:46 PST 2011' UNION ALL
  SELECT 'Fri Nov 04 07:50:21 PDT 2011' UNION ALL
  SELECT 'Thu Dec 01 00:00:00 PST 2011'
)
SELECT
  OldDateCol,
  NewDateCol = CAST(SUBSTRING(STUFF(OldDateCol, 21, 4, ''), 5, 99) AS datetime)
FROM StringDates

即,STUFF删除时区部分,SUBSTRING省略星期几。

以下是结果集:

OldDateCol                    NewDateCol
----------------------------  -----------------------
Mon Nov 14 14:52:46 PST 2011  2011-11-14 14:52:46.000
Fri Nov 04 07:50:21 PDT 2011  2011-11-04 07:50:21.000
Thu Dec 01 00:00:00 PST 2011  2011-12-01 00:00:00.000

另一方面,如果您(或可能最终)使用datetimeoffset列来存储转换后的值并且有兴趣保留时区位信息,则可以尝试以下方法:< / p>

;
WITH StringDates (OldDateCol) AS (
  SELECT 'Mon Nov 14 14:52:46 PST 2011' UNION ALL
  SELECT 'Fri Nov 04 07:50:21 PDT 2011' UNION ALL
  SELECT 'Thu Dec 01 00:00:00 PST 2011'
),
DatesAndTimeZones AS (
  SELECT
    OldDateCol,
    NewDateCol = CAST(SUBSTRING(STUFF(OldDateCol, 21, 4, ''), 5, 99) AS datetime),
    TimeZoneName = SUBSTRING(OldDateCol, 21, 4)
  FROM StringDates
),
TimeZones (Name, Offset) AS (
  SELECT 'PST', '-08:00' UNION ALL
  SELECT 'PDT', '-07:00'
)
SELECT
  d.OldDateCol,
  NewDateTimeOffsetCol = TODATETIMEOFFSET(d.NewDateCol, t.Offset)
FROM DatesAndTimeZones d
  INNER JOIN TimeZones t ON d.TimeZoneName = t.Name

此处转换分两步完成。

第一步将字符串转换为datetime值,与之前相同,并从中提取时区名称。

基本上,这两个值足以将datetime转换为datetimeoffset,但SQL Server无法识别时区名称,它只能理解偏移,格式为+hh:mm-hh:mm。因此,您需要使用相应的偏移替换名称,这可以在参考表的帮助下完成(上面的TimeZones CTE扮演其角色)。

所以下一个(也是最后一个)步骤是加入参考表并调用TODATETIMEOFFSET()函数来获得最终结果。

以下是第二个查询的结果:

OldDateCol                    NewDateTimeOffsetCol
----------------------------  ----------------------------------
Mon Nov 14 14:52:46 PST 2011  2011-11-14 14:52:46.000 -08:00
Fri Nov 04 07:50:21 PDT 2011  2011-11-04 07:50:21.000 -07:00
Thu Dec 01 00:00:00 PST 2011  2011-12-01 00:00:00.000 -08:00

参考文献: