web-dev-qa-db-fra.com

Comment comparer des chaînes dans deux colonnes VARCHAR différentes?

J'ai besoin d'un moyen de comparer le contenu de deux colonnes varchar, nommées fistname et lastname en conséquence, et si le contenu existe dans firstname, puis supprimez-le de lastname. Idéalement, je voudrais faire ceci sans requête de mise à jour, mais si c'est le seul moyen d'y parvenir, je peux suivre cette voie.

Voici des exemples DDL et DML:

Declare @BadData Table
(
    firstname varchar(500)
    ,lastname varchar(500)
)

Insert Into @BadData (firstname, lastname) Values
('Bridget Jones', 'Jones, III'), ('Butch', 'Jones'), ('Key West', 'West')
,('Bob Marly', 'Junior')

Select * From @BadData

Ce qui donne l'ensemble de résultats de:

firstname       lastname
-------------   ----------
Bridget Jones   Jones, III
Butch           Jones
Key West        West
Bob Marly       Junior

Mon jeu de résultats souhaité est:

firstname       lastname
-------------   --------
Bridget Jones   , III
Butch   Jones
Key West    
Bob Marly       Junior

Je veux supprimer le texte (c'est-à-dire le contenu) de la colonne lastname s'il existe dans la colonne firstname.

Comment cela peut-il être fait via une instruction UDF ou case dans SQL Server 2008 R2?

3
IcyPopTarts

J'ai d'abord utilisé une fonction de chaîne fractionnée que j'ai empruntée (encore) à cela réponse . Et j'ai ajouté une colonne ID (je suppose que votre table a un champ PK pour identifier chaque enregistrement.)

CREATE TABLE MyTable
(
    Id int IDENTITY,
    FirstName varchar(500),
    LastName varchar(500)
)

INSERT INTO MyTable (FirstName, LastName) 
VALUES ('Bridget Jones', 'Jones, III'), ('Butch', 'Jones'), ('Key West', 'West'),('Bob Marly', 'Junior');
GO
CREATE FUNCTION dbo.fnSplit(@Input Varchar(1000), @Splitter VarChar(10)) 
RETURNS TABLE AS
RETURN
    SELECT Split.a.value('.', 'VARCHAR(1000)') AS Data 
    FROM (SELECT CAST ('<M>' + REPLACE(@Input, @Splitter, '</M><M>') + '</M>' AS XML) AS Data) AS A 
    CROSS APPLY Data.nodes ('/M') AS Split(a);
GO

Maintenant, en utilisant un CROSS APPLY avec vos données:

    SELECT *
    FROM   MyTable t1 
    CROSS APPLY fnSplit(t1.FirstName, ' ') t2
    WHERE CHARINDEX(t2.Data, t1.LastName) > 0;
GO

Vous pouvez identifier les enregistrements où LastName contient un mot de FirstName:

 Id | Prénom | Nom | Données 
 -: | : --------- : --------- | : ---- 
 1 | Bridget Jones | Jones, III | Jones 
 3 | Key West | Ouest | Ouest 

En utilisant les identifiants renvoyés par la requête précédente, vous pouvez mettre à jour votre table:

WITH found AS
(
    SELECT Id, FirstName, LastName, Data
    FROM   MyTable t1 
    CROSS APPLY fnSplit(t1.FirstName, ' ') t2
    WHERE CHARINDEX(t2.Data, t1.LastName) > 0
)
UPDATE     T1
SET        T1.LastName = RTRIM(LTRIM(REPLACE(T1.LastName, Data, '')))
FROM       MyTable t1
INNER JOIN found t2
ON         t1.Id = t2.Id;
GO
 2 lignes affectées 

Et voici le résultat final:

SELECT * FROM MyTable;
GO
 Id | Prénom | Nom 
 -: | : ------------ | : ------- 
 1 | Bridget Jones | , III 
 2 | Butch | Jones 
 3 | Key West | 
 4 | Bob Marly | Junior 

dbfiddle --- (ici

7
McNets