当前位置: 首页 > 知识库问答 >
问题:

Sybase-在SQL中创建一个测试,比较两个具有相同子字符串但位置不同的字符串的列

易炳
2023-03-14

标题可能有点难以理解,因为我不擅长总结事情,但我试图做的事情实际上非常简单(在任何其他语言中)。

我想测试赛贝斯表中的一些数据,特别是两列。这两列有冒号分隔的字符串——不幸的是,两列之间每个子字符串的位置不一样。是这样的:

第1栏

子字符串1:子字符串3:子字符串5

子字符串2:子字符串4:子字符串6

column_2

子字符串3:子字符串1:子字符串5

Substring6: substring2: substring4

我想做的是,如果column1的子字符串不等于column2的子字符串,则提供一个简单的通过/失败状态。我不关心子字符串的顺序,也不能在它们到达表之前更改它们的顺序。我只想说:

无论顺序如何,如果列1具有与列2相同的内容,并且如果列1或列2包含其他列中不存在的信息,则测试将失败。

我可以用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,不过我对数据库设置的了解不多。

共有3个答案

荣德厚
2023-03-14

我认为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个元素的字符串,那么对它的维护将不太理想,但目前的现实是,我们在很长一段时间内都不会看到这一点,当我们在上游进行代码更改时,这个测试只对冒烟测试是必要的。

虽然这个解决方案既丑陋又不雅观,但扩展是一个相当简单的复制粘贴工作,并在这里和那里改变一些事情。

编辑:我可能有一些错误的开始位置,但我的解决方案的一般要点基本上是a的子串=b的子串,如果通过,如果不通过,那么继续前进并失败。

步博厚
2023-03-14

赛贝斯ASE没有任何内置函数可以执行所需的比较。

赛贝斯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

笔记:

  • 函数名以“sp_u3;”开头,并安装在SybsystemProcs数据库中;这允许从数据服务器中的任何数据库调用该函数;否则,您可以根据需要为函数命名,并将其安装在数据(待比较)所在的同一数据库中

函数的一些示例调用:

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

笔记

  • 当调用UDF时,您必须包括UDF的所有者(上面示例中的'dbo.'前缀)

如果运行赛贝斯ASE 16,您可以访问表@变量

虽然您仍然需要创建UDF,但是UDF可以将2x输入字符串解析为table@变量,然后对2x table@变量运行基于集合的查询来确定“通过”或“失败”。

岑光熙
2023-03-14

我并没有完全理解这个问题,特别是如果我们知道字符串的实际长度,如果我们知道,这很好,如果我们不知道,下面的问题会变得更难。现在,我假设是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
 类似资料:
  • 我在JQuery的AJAX请求中发现了一个回显值的有趣问题,但我没有为它提供一个answare: 如果你需要更多的信息告诉我!我希望任何人都知道是什么导致了这个问题!

  • 问题内容: 有什么方法可以像下面这样在SQL Server 2008存储过程中比较两个字符串? 如果字符串相同,则返回0 如果根据当前的排序顺序,第一个参数小于第二个参数,则返回-1。 否则返回1。 以上方法我在MySQL中找到,但在SQL Server中找不到。 问题答案: SQL Server中没有直接的字符串比较功能 笔记 您可以使用CREATE FUNCTION等通过UDF进行包装 您可能

  • 例如,我们有一个字符串:asd/asd/asd/1#s_ 我需要匹配以下部分:/asd/1#s_或asd/1#s_如何使用普通正则表达式? 我试过像这样的消极前瞻,但它不起作用 它匹配这个“前缀/asd/1#s_”,我需要匹配“/asd/1#s_”中的这个“/asd/1#”,我需要匹配“/asd/1#s_”,而没有所有前面的 /asd/'s 匹配应该与普通正则表达式没有任何编程语言的任何帮助函数h

  • 问题内容: 我有两个字符串,分别为@CountryLocationIDs和@LocationIDs,其值分别为: 然后,我需要另一个变量中的输出为: 任何人都请帮忙…预先感谢… 问题答案: 我创建了一个表值函数,该函数接受两个参数,第一个是带有ID的字符串,第二个是字符串中的定界符。 创建函数后,只需使用set运算符即可: 已编辑 有了它,您将自动从两个字符串中获得不同的值,因此您不需要使用子句

  • 问题内容: 这是我在采访中遇到的一个问题。 我有两个字符串定义为 我的问题是这两个引用是否指向相同的内存位置。通常,当我们创建相同的字符串(不带new关键字)时,内容是否仅在内存中存储一​​次,并且具有相同内容的所有String对象仅引用同一位置,而没有多余地存储字符串“ Java”?s1和s2的哈希码相同。但是哈希码是否直接取决于对象的内存位置? 问题答案: 合并相同字符串的过程称为“ inte

  • 如何检查一个字符串是否在另一个字符串中,但匹配项需要在前面,而不是中间或最后。例如,a="