【问题标题】:SQL Replace date in stringSQL 替换字符串中的日期
【发布时间】:2019-03-04 12:15:57
【问题描述】:

我有一个不总是相同的字符串文件名,我正在努力想出一些干净且不太繁琐的东西,它将去除刺痛的日期部分并将其替换为 yyyyMMdd 或 yyMMdd(取决于文件名字符串格式)。

例如,如果文件名如下所示:

g_monthlysales_20130930_2500g.txt

我想把它转换成这个:

g_monthlysales_yyyyMMdd_2500g.txt

或者如果文件名看起来像这样:

gx130930rtwtg.txt

我想把它转换成这个:

 gxyyMMddrtwtg.txt

这些是文件名唯一可能的两种日期格式,并且大多数日期位于相同的位置,但其他文件名字符会有所不同,例如我也有 sx141001theuf.txt 或 @987654326 @

非常感谢任何帮助。

【问题讨论】:

  • 嗨,我会将这项任务分为两个步骤。 1) 从字符串中获取数字 2) 将数字转换为日期(比如循环遍历您所在地区可接受的格式的函数)。
  • 您在这里查看了多少种不同的日期格式?
  • 9 月没有 31 天。您想只检测字符串中的正确日期吗?
  • 对可能的日期格式的详细信息进行了上述编辑。那是我的错误,字符串中的日期将始终是有效日期,因此无需验证它们。
  • 大部分日期都在同一个位置 -- 所以你不只是有两种文件名格式吗?有多少种变化?

标签: sql date replace sql-server-2012


【解决方案1】:

如果日期总是在同一个位置并且文件总是在同一个格式,那么这个代码应该可以工作:

declare @testString nvarchar(100)
declare @result nvarchar(100)

set @testString = 'h_monthlysales_20130930_1000v.txt'
-- set @testString = 'g_monthlysales_20130930_2500g.txt'
-- set @testString = 'gx130930rtwtg.txt'
-- set @testString = 'sx141001theuf.txt'

IF patindex('_______________[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_[0-9][0-9][0-9][0-9]_.txt',@testString) = 1
BEGIN
    set @result = SUBSTRING(@testString,1,15)+'yyyyMMdd'+SUBSTRING(@testString,24,100)
END
ELSE IF patindex('__[0-9][0-9][0-9][0-9][0-9][0-9]_____.txt',@testString) = 1
BEGIN
    set @result = SUBSTRING(@testString,1,2)+'yyMMdd'+SUBSTRING(@testString,9,100)
END
ELSE
BEGIN
    set @result = @testString
END

print @result

如果日期可以更改位置,那么如果日期始终是第一个数值,则类似的方法将起作用(对于第二个日期格式,请编写类似的代码):

declare @testString nvarchar(100)
declare @result nvarchar(100)
declare @datePostion int

--set @testString = 'h_monthlysales_20130930_1000v.txt'
set @testString = 'g_monthlysalesxyz_20130930_2500g.txt'

set @datePostion = patindex('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%.txt',@testString)
IF @datePostion > 0
BEGIN   
    set @result = SUBSTRING(@testString,1,@datePostion-1)+'yyyyMMdd'+SUBSTRING(@testString,@datePostion+8,100)
END
ELSE
BEGIN
    set @result = @testString
END

print @result 

【讨论】:

  • 为什么不直接使用case 表达式而不是所有if 块?
  • 我更习惯 if 比 case :)。同样在第二个示例中,当日期可以更改位置时,如果语法您将不得不执行 patindex 三次。首先检查条件是否满足,然后在构建结果时检查两次 - 也许可以对其进行优化。
  • 在 SQL 数据库中工作时,像我这样的基于集合的解决方案几乎总是比按值或逐行方法执行得更好,这是您的解决方案可以在多个数据库上实施的唯一方法文件名。
【解决方案2】:

这将首先找到任何 8 位数字,然后是任何 6 位数字并尝试将其转换为 date 值。这将适用于文件名中任何位置的日期,但几乎肯定会产生糟糕的性能:

declare @t table(f varchar(50));
insert into @t values('g_monthlysales_20130930_2500g.txt'),('gx130930rtwtg.txt'),('sx141001theuf.txt'),('h_monthlysales_20130930_1000v.txt');

select f
      ,case when patindex('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',f) > 0
            then convert(date,substring(f,patindex('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',f),8),112)
            else convert(date,substring(f,patindex('%[0-9][0-9][0-9][0-9][0-9][0-9]%',f),6),12)
            end as d
from @t;

输出:

+-----------------------------------+------------+
|                 f                 |      d     |
+-----------------------------------+------------+
| g_monthlysales_20130930_2500g.txt | 30.09.2013 |
| gx130930rtwtg.txt                 | 30.09.2013 |
| sx141001theuf.txt                 | 01.10.2014 |
| h_monthlysales_20130930_1000v.txt | 30.09.2013 |
+-----------------------------------+------------+

如果您可以找到所有可能的格式,或者更好地更改您的导入例程以获得一致的文件名格式,您可以通过缺少通配符来使此查询更加高效。

【讨论】:

    【解决方案3】:

    如果我没有正确阅读问题,我们不是在尝试隔离日期,而是在尝试覆盖它们。这应该可以做到这一点,或者无论如何都会让你朝着那个方向前进。

    DECLARE @t TABLE (FileNme VARCHAR(50));
    INSERT INTO
      @t
    VALUES
      ('g_monthlysales_20130930_2500g.txt')
     ,('gx130930rtwtg.txt')
     ,('sx141001theuf.txt')
     ,('h_monthlysales_20130930_1000v.txt');
    
    SELECT
      FileNme
     ,CASE
        WHEN PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', FileNme) > 0 
          THEN STUFF(FileNme, PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', FileNme), 8, 'yyyyMMdd')
        ELSE STUFF(FileNme, PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9]%', FileNme), 6, 'yyMMdd')
      END AS NewNme
    FROM
      @t;
    

    结果:

    +-----------------------------------+-----------------------------------+
    |              FileNme              |              NewNme               |
    +-----------------------------------+-----------------------------------+
    | g_monthlysales_20130930_2500g.txt | g_monthlysales_yyyyMMdd_2500g.txt |
    | gx130930rtwtg.txt                 | gxyyMMddrtwtg.txt                 |
    | sx141001theuf.txt                 | sxyyMMddtheuf.txt                 |
    | h_monthlysales_20130930_1000v.txt | h_monthlysales_yyyyMMdd_1000v.txt |
    +-----------------------------------+-----------------------------------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-14
      相关资源
      最近更新 更多