Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server比较地址字符串的一部分,2列_Sql Server_String_Tsql_Comparison - Fatal编程技术网

Sql server SQL Server比较地址字符串的一部分,2列

Sql server SQL Server比较地址字符串的一部分,2列,sql-server,string,tsql,comparison,Sql Server,String,Tsql,Comparison,我想寻求有关如何对存储在两个单独列中的两个地址值进行部分字符串比较的帮助。我只需要识别匹配的值,即使匹配不是100%。我不关心街道方向的值:N、S、E、W,或者它是套房、公寓还是街道类型(rd、st、dr、cr等)。也许只需匹配第一个值,即门牌号即可满足要求 例如: Column1 Column2 17 Wickham CT 17 S WICKHAM CT # 2 << This is a partial match, include 6818 Chester

我想寻求有关如何对存储在两个单独列中的两个地址值进行部分字符串比较的帮助。我只需要识别匹配的值,即使匹配不是100%。我不关心街道方向的值:N、S、E、W,或者它是套房、公寓还是街道类型(rd、st、dr、cr等)。也许只需匹配第一个值,即门牌号即可满足要求

例如:

Column1          Column2
17 Wickham CT    17 S WICKHAM CT # 2 << This is a partial match, include
6818 Chester DR  6801 CHESTER DR # A << This is a partial match, include
6301 Raymond RD  6301 RAYMOND RD     << This is a full match, include
6217 Raymond RD  PO BOX 45581        << This doesn't match, don't include
在这种情况下,从前两条记录来看,第一条记录似乎是匹配的,但事实并非如此,因为所有者有多个地址,第三条记录是很好的匹配,因为地址匹配,所有者只有一个地址。如何仅选择地址匹配的记录,并且所有者只有一个地址号?我希望这是有道理的

再次感谢您

尝试使用。此链接提供了一些如何使用T-SQL实现它的示例

Levenshtein距离基本上为两个字符串之间的差异提供一个值。您可以为查询提供一个可接受的值,并返回任何达到该可接受阈值的值。

您也可以尝试使用

MS SQL的完美示例

下面是我的快速组装示例:

--helper function to convert string to ASCII column
CREATE FUNCTION dbo.fn_StringToASCII
(
    @text VARCHAR(MAX)
)
RETURNS @Result TABLE
(
    POS INT,
    NUM INT
)
AS
BEGIN
    DECLARE @i INT
    SET @i = 1
    WHILE @i <= LEN(@text)
    BEGIN
        INSERT INTO @Result
        (
            POS,
            NUM
        )
        VALUES
        (@i, ASCII(SUBSTRING(@text, @i, 1)))
        SET @i = @i + 1
    END
    RETURN;
END;

-- test example
 CREATE TABLE test1(ID INT, ADDR1 VARCHAR(20));
 CREATE TABLE test2(ID INT, ADDR2 VARCHAR(20));

 INSERT INTO dbo.test1
(
    ID,
    ADDR1
)
VALUES
(1, '17 Wickham CT'),
(2, '6818 Chester DR'),
(3, '6217 Raymond RD'),
(4, 'TEST');

INSERT INTO dbo.test2
(
    ID,
    ADDR2
)
VALUES
(1, '17 S WICKHAM CT # 2'),
(2, '6801 CHESTER DR # A'),
(3, 'PO BOX 45581'),
(4, 'TEST');

 --query with coeff
SELECT ISNULL(t1.ID, c2.ID) AS ID,
       (AVG(c1.NUM * c2.NUM) - (AVG(c1.NUM) * AVG(c2.NUM))) / (STDEVP(c1.NUM) * STDEVP(c2.NUM)) AS  Coeff
FROM dbo.test1 t1
    CROSS APPLY dbo.fn_StringToASCII(LOWER(t1.ADDR1)) c1
    RIGHT JOIN
    (
        SELECT t2.ID,
               c2.*
        FROM dbo.test2 t2
            CROSS APPLY dbo.fn_StringToASCII(LOWER(t2.ADDR2)) c2
    ) c2
        ON c2.ID = t1.ID
           AND c2.POS = c1.POS
WHERE 1 = 1
GROUP BY ISNULL(t1.ID, c2.ID);


DROP TABLE dbo.test1
DROP TABLE dbo.test2

/*
results
ID  Coeff
1   0.957280794307261
2   1.58310202187124
3   -0.397204343866094
4   0.987654320987654
*/
--将字符串转换为ASCII列的帮助函数
创建函数dbo.fn\u StringToASCII
(
@text VARCHAR(最大值)
)
返回@Result表
(
位置INT,
NUM INT
)
像
开始
声明@i INT
设置@i=1

而@i这是一个很好的习惯。我认为您需要C#或其他编程语言。我打赌你可以在TSQL游标中完成,但这会很痛苦。Levenschtein distance my做你想做的。谢谢,我看了你的文章,但是我不知道如何实现在函数中创建edit_distance_,然后传入你的两个值。第三个是一个阈值,您需要确定匹配是否可行(10是一个任意数字,您需要自己调整)<代码>选择编辑距离(第1列、第2列、第10列)
17 S威克姆CT#2 17**WICKHAM CT****需要6次编辑才能匹配,因此本例中的levenshtein距离为6。本例中的每个星号都是删除。上一个示例的距离为14,因为几乎每个字符都需要替换。
--helper function to convert string to ASCII column
CREATE FUNCTION dbo.fn_StringToASCII
(
    @text VARCHAR(MAX)
)
RETURNS @Result TABLE
(
    POS INT,
    NUM INT
)
AS
BEGIN
    DECLARE @i INT
    SET @i = 1
    WHILE @i <= LEN(@text)
    BEGIN
        INSERT INTO @Result
        (
            POS,
            NUM
        )
        VALUES
        (@i, ASCII(SUBSTRING(@text, @i, 1)))
        SET @i = @i + 1
    END
    RETURN;
END;

-- test example
 CREATE TABLE test1(ID INT, ADDR1 VARCHAR(20));
 CREATE TABLE test2(ID INT, ADDR2 VARCHAR(20));

 INSERT INTO dbo.test1
(
    ID,
    ADDR1
)
VALUES
(1, '17 Wickham CT'),
(2, '6818 Chester DR'),
(3, '6217 Raymond RD'),
(4, 'TEST');

INSERT INTO dbo.test2
(
    ID,
    ADDR2
)
VALUES
(1, '17 S WICKHAM CT # 2'),
(2, '6801 CHESTER DR # A'),
(3, 'PO BOX 45581'),
(4, 'TEST');

 --query with coeff
SELECT ISNULL(t1.ID, c2.ID) AS ID,
       (AVG(c1.NUM * c2.NUM) - (AVG(c1.NUM) * AVG(c2.NUM))) / (STDEVP(c1.NUM) * STDEVP(c2.NUM)) AS  Coeff
FROM dbo.test1 t1
    CROSS APPLY dbo.fn_StringToASCII(LOWER(t1.ADDR1)) c1
    RIGHT JOIN
    (
        SELECT t2.ID,
               c2.*
        FROM dbo.test2 t2
            CROSS APPLY dbo.fn_StringToASCII(LOWER(t2.ADDR2)) c2
    ) c2
        ON c2.ID = t1.ID
           AND c2.POS = c1.POS
WHERE 1 = 1
GROUP BY ISNULL(t1.ID, c2.ID);


DROP TABLE dbo.test1
DROP TABLE dbo.test2

/*
results
ID  Coeff
1   0.957280794307261
2   1.58310202187124
3   -0.397204343866094
4   0.987654320987654
*/