如何解决从格式 yyyy_d_m
在 sql Server 中,我有一列包含格式为 yyyy_d_m_(randominteger)_(randominteger)_blahblahblah 字符串的字符串。
所以
列 |
---|
2021_28_6_42_blahblahblahblah |
2021_8_12_17_4_blahblahblahblah |
等
我需要检索第三个下划线之前的所有内容并将其转换为日期。
我已经尝试在以下方面使用变体:
SELECT
left(column,patindex('%[^0-9]%',column))
然而,尾随整数的长度是不同的。日期和月份也是如此,因为它们没有输入零。我也遇到了下划线作为通配符的问题。
解决方法
DECLARE @text VARCHAR(200) = '2021_8_12_17_4_blahblahblahblah';
-- https://stackoverflow.com/questions/8726111/sql-server-find-nth-occurrence-in-a-string
with T as (
select 0 as row,charindex('_',@text) pos,@text as txt,1 as occurance
union all
select pos + 1,@text,pos + 1),occurance+1
from T
where pos > 0
)
select
@text,pos,occurance,substring(@text,pos) as "DATE"
from T
where occurance=3
- 首先我声明一个变量(名为
@text
) - 在 stackoverflow 的帮助下,该链接是使用 Google 的结果之一:对于 tsl find character in string,还有一些小改动
结果:
pos occurance DATE
--------------------------------- ----------- ----------- ------------
2021_8_12_17_4_blahblahblahblah 10 3 2021_8_12
其中 DATE
下的列是您要查找的文本。
附言用这段代码创建一个函数会更漂亮,但是......?
,为了简洁起见,计算 CROSS APPLY 中前两个下划线的位置。
select datefromparts(substring(t.d,1,i1 - 1),substring(t.d,i2 + 1,t.d,i2 + 1) - i2 - 1),i1 + 1,i2 - i1 - 1)
) dt
from (
values
('2021_8_12_17_4_blahblahblahblah'),('2021_28_6_42_blahblahblahblah')
) t(d) -- your table here
cross apply(
select charindex('_',1) i1,1) + 1) i2
) t2
,
另一种带有一点 JSON 的选项
Select A.*,AsDate = datefromparts(JSON_VALUE(S,'$[0]'),JSON_VALUE(S,'$[2]'),'$[1]')
)
From YourTable A
Cross Apply ( values ( '["'+replace([column],'_','","')+'"]' ) ) B(S)
结果
column AsDate
2021_28_6_42_blahblahblahblah 2021-06-28
2021_8_12_17_4_blahblahblahblah 2021-12-08
注意:
如果您的字符串中碰巧有双引号等,则可能需要应用 string_escape()
...
Cross Apply ( values ( '["'+replace(STRING_ESCAPE([column],'json'),"')+'"]' ) ) B(S)
,
这是一个非常糟糕的设计。您仍然可以将其转换为日期,但如果性能是一个问题,那么我将使用 CLR 函数。
create table baddata (bad varchar(100));
insert into baddata (bad) values
('2021_28_6_42_blahblahblahblah'),('2021_8_12_17_4_blahblahblahblah');
with bd (bad,v,rn) as
(
select bad,cast(v as int),row_number() over (partition by bad order by bad)
from baddata
cross apply (select top(3) value
from string_split(baddata.bad,'_')) t(v)
),ydm (bad,y,d,m) as
(
select bad,sum(cast(case when rn=1 then v end as int)) y,sum(cast(case when rn=2 then v end as int)) d,sum(cast(case when rn=3 then v end as int)) m
from bd
group by bad
)
select bad,datefromparts(y,m,d) [date]
from ydm;
,
您需要计算前 3 个位置中下划线的位置。以下工作通过连续 CROSS APPLY'ing 获得 CHARINDEX 位置。像这样
void Update()
{
movement = Input.GetAxis("Horizontal");
if (((transform.localScale.x > 0 && movement < 0) ||
(transform.localScale.x < 0 && movement > 0))
&& !isTurning)
{
isTurning = true;
turningCounter = 5;
StartCoroutine("countdownTurn"); // simply ticks down turningCounter every 0.n seconds
}
if (turningCounter == 3) setRenderDirection(); // ie. routine for transforming localscale (mirroring the image)
// show player in profile at end of counter
profileRenderer.enabled = turningCounter < 1;
// show player turning towards camera on 4 and away from camera on 1
turningRenderer.enabled = turningCounter == 4 || turningCounter == 1;
// show player looking dead center for 2 counts
centerRenderer.enabled = turningCounter == 2 || turningCounter == 3;
if (turningCounter < 1)
{
isTurning = false;
defaultAnimator.SetBool("isTurning",false);
}
}
select datefromparts(ci2.dt_yr,ci4.dt_mo,ci3.dt_day) dt_from_parts
from (values ('2021_8_12_17_4_blahblahblahblah'),('2021_28_6_42_blahblahblahblah')) string(dt)
cross apply (values (charindex('_',string.dt,1))) ci1(loc)
cross apply (values (charindex('_',ci1.loc+1),left(string.dt,ci1.loc-1))) ci2(loc,dt_yr)
cross apply (values (charindex('_',ci2.loc+1),substring(string.dt,ci1.loc+1,(ci2.loc-ci1.loc)-1))) ci3(loc,dt_day)
cross apply (values (substring(string.dt,ci2.loc+1,(ci3.loc-ci2.loc)-1))) ci4(dt_mo);
假设这段代码难看,而且看不完。它可以被提取到一个 SCHEMABOUND 内联表值函数中,你可以使用 CROSS APPLY 来简化查询。
dt_from_parts
2021-12-08
2021-06-28
然后查询可能看起来像这样
drop function if exists dbo.test_fnExtractDate;
go
create function dbo.test_fnExtractDate(
@input_string varchar(64))
returns table with schemabinding as return
select datefromparts(ci2.dt_yr,ci3.dt_day) dt_from_parts
from (values (@input_string)) string(dt)
cross apply (values (charindex('_',(ci3.loc-ci2.loc)-1))) ci4(dt_mo);
go
select fex.*
from (values ('2021_8_12_17_4_blahblahblahblah'),('2021_28_6_42_blahblahblahblah')) string(dt)
cross apply dbo.test_fnExtractDate(string.dt) fex
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。