【问题标题】:SQL Server : how to replace or convert string "ddMMM" to date "MMMdd"?SQL Server:如何将字符串“ddMMM”替换或转换为日期“MMMdd”?
【发布时间】:2020-09-25 14:43:47
【问题描述】:

如何在[SQL Server]中进行替换或转换?

我有如下所示的表格:

startDate
varchar(5)
----------
08MAY
01JUN
02JUN
10JUN


station
varchar(4)
----------
ICN
LAX
SFO
ICN

startDate 列的类型为 varchar,但存储的数据类似于 'ddMMM'

我在这样的 SQL 查询中请求 01JUN ~ 10JUN...

select * 
from dbo.temp 
where convert(varchar(5), Startdate) >= convert(varchar(4), '01JUN')

...但是,错误的查询。

请给我建议

【问题讨论】:

标签: sql sql-server tsql date where-clause


【解决方案1】:

您应该真正修复您的数据模型,并将日期存储为类似日期的数据类型而不是字符串。将日期存储为字符串,尤其是这种不妥的格式,会使非常简单的事情变得比他们需要的复杂得多。

就 6 月的这 10 天,字符串比较就足够了:

where startdate between '01JUN' and '10JUN'

更通用的解决方案是将字符串转换为实际日期。假设您想要 2020 年的日期,那么:

where datefromparts(
    '2020'
    case right(startdate, 3)
        when 'JAN' then  1
        when 'FEB' then  2
        when 'MAR' then  3
        when 'APR' then  4
        when 'MAY' then  5
        when 'JUN' then  6
        when 'JUL' then  7
        when 'AUG' then  8
        when 'SEP' then  9
        when 'OCT' then 10
        when 'NOV' then 11
        when 'DEC' then 12
    end,
    left(startdate, 2)
) between '2020-06-01' and '20200610'

如果您想修复您的架构(这也是您应该关注的),您可以使用相同的转换技术:

-- create a new column
alter table mytable add startdate2 date;

-- set it
update mytable 
set startdate2 = datefromparts(
    '2020'
    case right(startdate, 3)
        when 'JAN' then  1
        when 'FEB' then  2
        when 'MAR' then  3
        when 'APR' then  4
        when 'MAY' then  5
        when 'JUN' then  6
        when 'JUL' then  7
        when 'AUG' then  8
        when 'SEP' then  9
        when 'OCT' then 10
        when 'NOV' then 11
        when 'DEC' then 12
    end,
    left(startdate, 2)
);

-- drop the old column
alter table mytable drop column startdate;

-- rename the new column
exec sp_rename 'mytable.startdate2' , 'startdate', 'COLUMN';

【讨论】:

    【解决方案2】:

    如果您要查找 DATE 或字符串,则不是 100% 清楚。以下有两种选择

    示例

    Declare @YourTable Table ([startDate] varchar(50))
    Insert Into @YourTable Values 
     ('08MAY')
    ,('01JUN')
    ,('02JUN')
    ,('10JUN')
    
    Select *
          ,AsADate   = try_convert(date,stuff(startDate,3,0,' ')+' 2020')
          ,AsAString = right(StartDate,3)+left(StartDate,2)
     from @YourTable
    

    退货

    startDate   AsADate     AsAString
    08MAY       2020-05-08  MAY08
    01JUN       2020-06-01  JUN01
    02JUN       2020-06-02  JUN02
    10JUN       2020-06-10  JUN10
    

    【讨论】:

      【解决方案3】:

      您将日期存储为varchar 的事实本身就是一个问题,并且您存储的版本是特定于语言的。理想情况下,您永远不应该将日期存储为varchar;他们的行为不一样。例如'02DEC'之前 31JAN''MAR17'之后 'APR01'

      为此,您需要先转换为date,然后再转换回varchar。这仅适用于基于语言的语言;如果LOGIN 使用法语、德语、日语,这将不起作用(要使其起作用,您需要修复数据模型)。​​

      SELECT V.YourColumn,
             UPPER(REPLACE(CONVERT(varchar(6),CONVERT(date,STUFF(V.YourColumn,3,0,' ') + ' 2000',100),107),' ','')) AS NewColumn
      FROM (VALUES('08MAY'),
                  ('01JUN'),
                  ('02JUN'),
                  ('10JUN'))V(YourColumn)
      

      这有几个部分。首先STUFFvarchar 的日期和月份部分之间注入一个空格;例如给'01 JUN'。然后我们将 ' 2000' 连接到值以创建一个起息日(2000 年是闰年,以防万一您有 '29FEB')。

      然后,一旦我们有了一个有效的格式日期,例如'01 JUN 2000',我们将CONVERT 使用样式100 (mon dd yyyy hh:miAM (or PM)) 转换为date。使用样式代码只需确保 CONVERT 应该可以工作,而不管基于 English 的语言如何。

      之后我们使用样式代码 107 (Mon dd, yyyy) 将 CONVERTdate 返回到 varchar。由于varchar 被定义为varchar(6),因此该值被截断为Mon dd

      最后,我们删除Mondd 之间的空格并应用UPPER 使字母大写。

      【讨论】:

        【解决方案4】:

        您需要将 startDate 列修复为标准日期,否则您会遇到问题,其中之一是您将如何过滤几天之外的数据,以及如果您的表中有 2 年的数据会发生什么,那么如何你要决定哪一年是你的过滤器吗?(2020 年 6 月 1 日或 2021 年 6 月 1 日)

        Select startDate,CONVERT(DATE,CONCAT(startDate,'2020')) as standard_startDate from tbl_date
        
        startDate   standard_startDate
        01JUN        2020-06-01
        02JUN        2020-06-02
        08MAY        2020-05-08
        
        ALTER TABLE tbl_date
        ALTER COLUMN startDate varchar(10)
        
        UPDATE tbl_date
        SET startDate = CONVERT(DATE,CONCAT(startDate,'2020'))
        
        ALTER TABLE tbl_date
        ALTER COLUMN startDate DATE
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-24
          • 2021-06-26
          相关资源
          最近更新 更多