0

両方のサブストリングが隣り合っている場合は、メインストリングからサブストリングの2番目の外観を削除する必要があります。例えば:

Jhon\Jhon\Jane\Mary\Bob終了する必要がありますJhon\Jane\Mary\Bob

しかし、変更しないでおく必要がMary\Jane\Mary\Bobあります。

誰もがこれを行うためのパフォーマンスの高い方法を思い付くことができますか?

'\'は異なる名前の区切り文字であるため、置換する部分文字列の制限として使用できます。

編集:これはSELECTステートメントで実行されるため、1行のソリューションである必要があり、変数を使用できません。また、名前が他の場所で繰り返されている場合は、そこに配置する必要があります。ファーストネームとセカンドネームの両方が同じである場合は、1つのオカレンスのみを削除してください。

4

2 に答える 2

2

これが1つの試みですが、私が言ったように、ネイティブT-SQLで高速なソリューションが得られるとは思いません。

まず、数値テーブルがまだない場合は、次のように作成します。

SET NOCOUNT ON;
DECLARE @UpperLimit int = 4000;

;WITH n AS
(
    SELECT rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
    FROM sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
)
SELECT [Number] = rn - 1
INTO dbo.Numbers FROM n
WHERE rn <= @UpperLimit + 1;

CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers([Number]);

次に、2つの関数を作成します。1つは文字列をテーブルに分割し、もう1つは最初の関数の結果を再結合しますが、後続の重複は無視します。

CREATE FUNCTION dbo.SplitStrings
(
    @List  nvarchar(4000),
    @Delim char(1)
)
RETURNS TABLE
AS
    RETURN ( SELECT 
      rn = ROW_NUMBER() OVER (ORDER BY CHARINDEX(@Delim, @List + @Delim)),
      [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
      CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
      FROM dbo.Numbers
      WHERE Number <= LEN(@List)
      AND SUBSTRING(@Delim + @List, [Number], 1) = @Delim
    );
GO

2番目の機能:

CREATE FUNCTION dbo.RebuildString
(
    @List  nvarchar(4000),
    @Delim char(1)
)
RETURNS nvarchar(4000)
AS
BEGIN
    RETURN ( SELECT newval = STUFF((
     SELECT @Delim + x.[Value] FROM dbo.SplitStrings(@List, @Delim) AS x
      LEFT OUTER JOIN dbo.SplitStrings(@List, @Delim) AS x2
      ON x.rn = x2.rn + 1
      WHERE (x2.rn IS NULL OR x.value <> x2.value)
      ORDER BY x.rn
      FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')
    );
END
GO

これで、質問で指定した2つのサンプルに対して試してみることができます。

;WITH cte(colname) AS
(
    SELECT 'Jhon\Jhon\Jane\Mary\Bob'
    UNION ALL SELECT 'Mary\Jane\Mary\Bob'
)
SELECT dbo.RebuildString(colname, '\')
FROM cte;

結果:

Jhon\Jane\Mary\Bob
Mary\Jane\Mary\Bob

ただし、使用を決定する前に、通常のデータサイズに対してこれを徹底的にテストすることを強く、強く、強くお勧めします。

于 2012-05-05T03:41:01.180 に答える
0

文字列操作に行くことにしました。クエリの実行にはもっと時間がかかると思いましたが、...ejem...本番環境...ejem...でテストしましたが、実行されなかったことがわかりました(驚いたことに)。それはきれいではありません、私は知っています、しかしそれは維持するのは簡単です...

これが私の最終的なクエリの簡略化されたバージョンです:

SELECT SOQ.PracticeId,
       CASE WHEN LEFT(SOQ.myString, SOQ.SlashPos) = SUBSTRING(SOQ.myString, SOQ.SlashPos + 1, LEN(LEFT(SOQ.myString, SOQ.SlashPos)))
            THEN RIGHT(SOQ.myString, LEN(SOQ.myString) - SOQ.SlashPos)
            ELSE SOQ.myString
       END as myString
  FROM (SELECT OQ.AllFields, OQ.myString, CHARINDEX('\', OQ.myString, 0) as SlashPos
          FROM MyOriginalQuery OQ) SOQ
于 2012-05-07T11:22:33.467 に答える