标题可能有点难以理解,因为我不善于总结事物,但我试图做的实际上是非常简单(在任何其他语言)。
我想在Sybase表中测试一些数据,特别是两列。这两列都有冒号分隔的字符串,不幸的是,每个子字符串的位置在两列之间并不相同。就像这样:
column_1
减1:减3:减5 减2:减4:减6
column_2
减3:减1:减5 减6:减2:减4
我想做的是,如果column1的子字符串不等于column2的子字符串,则提供简单的pass/fail状态。我不关心子串的顺序,也不能在它们到达桌子之前改变它们的顺序。我只想说:
如果column1具有与column2相同的内容(无论顺序如何),并且如果column1或column2包含的信息不存在于另一个信息中,则测试将失败。
我可以在类似Python的东西中蒙住眼睛,但我对SQL不太精通。下面是我查询这张桌子的大致方式:
select columna, columnb, columnc, columnd, column_1, column_2, CASE <do tests here> END as test_results from table有什么想法吗?我想保持一个尽可能简单的理想状态!
现在我知道每个子字符串都会有10个字符长,并且始终是冒号分隔的。然而,子串的数目可以从1到20不等(大多数是2或3)。
这是Sybase ASE,使用RapidSQL 8.6.1,我安装的ADE驱动程序的版本是15.07.00.1260,尽管我对我们的DB设置了解的并不多。
发布于 2017-06-16 16:57:10
我在这里并不完全关注这个问题,特别是如果我们知道字符串的实际长度,如果我们知道了,那就太好了,如果我们不这样做的话,下面的问题就变得更加困难了。现在,我假设10。而且,我不确定我是否跟随您的列示例,数据中是否有回车返回?还是那只是另一排?总之,一些代码可以让你开始:
if object_id('tempdb.dbo.#test') is not null drop table #test
create table #test
(
column1 varchar(50),
column2 varchar(50)
)
insert into #test
select
'substring1:substing2:substring3',
'substring3:substring1:substring2'
select
case
when substring(column1,1,charindex(':', column1)-1) =
substring(column2,charindex(':', column2)+1, 10)
then 'pass'
else 'fail'
end as Substring1Test,
case
when reverse(substring(reverse(column1),1,charindex(':', reverse(column1))-1) ) =
substring(column2,1,charindex(':', column2)-1)
then 'pass'
else 'fail'
end as Substring3Test
from #test发布于 2017-06-16 19:41:56
Sybase ASE没有任何可以执行所需比较的内置函数。
Sybase ASE 15.0.2+的一个可用选项是创建用户定义函数(UDF)的能力。
处理所需比较的UDF示例:
use sybsystemprocs
go
if object_id('dbo.sp_f_compare') is not NULL
drop function dbo.sp_f_compare
go
create function dbo.sp_f_compare
(@string1 varchar(300) = NULL
,@string2 varchar(300) = NULL
)
returns varchar(20)
as
declare @source varchar(300),
@target varchar(300),
@string varchar(20),
@pos smallint,
@loop tinyint,
@result varchar(20)
select @result = 'pass',
@loop = 1,
@source = @string1,
@target = ':' + @string2 + ':'
while @loop <= 2
begin
while @source is not NULL
begin
select @pos = charindex(':',@source)
if @pos = 0 select @pos = 300
select @string = ':' + substring(@source, 1,@pos-1) + ':',
@source = substring(@source,@pos+1,300 )
if charindex(@string,@target) = 0
begin
select @result = 'fail'
break
end
end
if @result = 'fail'
break
select @source = @string2,
@target = ':' + @string1 + ':',
@loop = @loop + 1
end
return @result
go
grant all on dbo.sp_f_compare to public
go备注:
函数的一些示例调用:
declare @string1 varchar(300),
@string2 varchar(300),
@string3 varchar(300),
@string4 varchar(300),
@string5 varchar(300)
select @string1 = 'substring1:substring3:substring5',
@string2 = 'substring3:substring1:substring5',
@string3 = 'substring2:substring4:substring6',
@string4 = 'substring6:substring2:substring4',
@string5 = 'substring2:substring4:substring6:substring7'
select dbo.sp_f_compare(@string1, @string2) as '1v2',
dbo.sp_f_compare(@string3, @string4) as '3v4',
dbo.sp_f_compare(@string1, @string3) as '1v3',
dbo.sp_f_compare(@string3, @string5) as '3v5',
dbo.sp_f_compare(@string5, @string3) as '5v3'
go
1v2 3v4 1v3 3v5 5v3
---------- ---------- ---------- ---------- ----------
pass pass fail fail fail备注:
如果运行Sybase ASE 16,您可以访问表@变量。
当您仍然需要创建一个UDF时,表示UDF可以将2x输入字符串解析为表@变量,然后对2x表@变量运行一个基于集合的查询,以确定'pass‘或'fail’。
发布于 2017-06-23 18:34:47
UDF解决方案是我认为最适合经常重用的东西的解决方案。然而,就我的目的而言,我的努力程度只是略高于我想要投资的水平。因此,我跳过了一个动态的、干净的、高效的、自动的解决方案,并使用了一个强力的解决方案,可以归结为这样的逻辑:我有两个字符串,我想比较任何位置上的任何元素都可以存在于另一个字符串中的任何位置(元素是由一个冒号分隔的10个字符的子字符串)。这不是一个很好的循环或类似的东西,这是我的解决方案:
CASE
when substring(batch_ids, 1, 10) = substring(offers,1,10) then "PASS"
when substring(batch_ids, 1, 10) = substring(offers,13,10) then "PASS"
when substring(batch_ids, 1, 10) = substring(offers,24,10) then "PASS"
when substring(batch_ids, 1, 10) = substring(offers,35,10) then "PASS"
when substring(batch_ids, 13, 10) = substring(offers,1,10) then "PASS"
when substring(batch_ids, 13, 10) = substring(offers,13,10) then "PASS"
when substring(batch_ids, 13, 10) = substring(offers,24,10) then "PASS"
when substring(batch_ids, 13, 10) = substring(offers,35,10) then "PASS"
when substring(batch_ids, 24, 10) = substring(offers,1,10) then "PASS"
when substring(batch_ids, 24, 10) = substring(offers,13,10) then "PASS"
when substring(batch_ids, 24, 10) = substring(offers,24,10) then "PASS"
when substring(batch_ids, 24, 10) = substring(offers,35,10) then "PASS"
when substring(batch_ids, 35, 10) = substring(offers,1,10) then "PASS"
when substring(batch_ids, 35, 10) = substring(offers,13,10) then "PASS"
when substring(batch_ids, 35, 10) = substring(offers,24,10) then "PASS"
when substring(batch_ids, 35, 10) = substring(offers,35,10) then "PASS"else "FAIL"
end as TestResults从本质上讲,它接受第一列的第一个元素,从位置1开始的子字符串和长10个字符的子字符串(即1234567890),并将其与位置1-10、13-23、24-34和35-45中的第二个字符串的子字符串进行比较。然后根据第二列中相同的位置检查第一个字符串的第二个子字符串,依此类推。这确实意味着,如果我们有一个包含4个以上元素的字符串,那么它的维护就不太理想了,但目前的现实是,我们不会在很长一段时间内看到这一点,而且只有当我们对上游代码进行更改时,才需要进行冒烟测试。
虽然这个解决方案丑陋和不优雅,但是扩展是一个相当简单的copy+paste工作,并且在这里和那里改变了一些东西。
编辑:我可能有一些错误的起始位置,但是我的解决方案的基本要点是做a= b的子字符串,如果是这样的话,如果没有,那么继续前进,失败。
https://stackoverflow.com/questions/44594200
复制相似问题