Проблема с корректной заменой сокращенного текста в SQL
Я пытаюсь заменить кучу трудных для расшифровки сокращений соответствующими подробными описаниями. У меня есть таблица под названием "Сокращения", которая просто содержит список сокращений, которые нужно искать, и соответствующие описания, на которые они должны быть изменены. Кроме того, таблица "Replaced" содержит список неизмененных сокращенных описаний, которые я хотел бы изменить в одном столбце под названием "DescriptionCodes".
Данные, которые я пытаюсь изменить, представляют собой список различных чаев. Например, запись "TADIN HB GR" будет сокращением от "TADIN HERBAL BAG GREEN"
Код SQL, который я сейчас использую, выглядит следующим образом:
BEGIN TRANSACTION
DECLARE @Desc varchar(500)
DECLARE @Abbr varchar(500)
DECLARE contact_cursor CURSOR FOR
SELECT Description, Abbrv FROM dbo.Abbreviations
OPEN contact_cursor
FETCH NEXT FROM contact_cursor
INTO @Desc, @Abbr
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Changing ' + @Abbr + ' to ' + @Desc
UPDATE Replaced
SET DescriptionCodes = REPLACE(DescriptionCodes, @Abbr, @Desc)
WHERE DescriptionCodes LIKE CONCAT('% ', @Abbr, ' %')
FETCH NEXT FROM contact_cursor
INTO @Desc, @Abbr
END
CLOSE contact_cursor
DEALLOCATE contact_cursor
COMMIT
Конечно, проблема, с которой я сталкиваюсь, заключается в том, что после применения аббревиатуры подробное описание может содержать подстроку, соответствующую другой аббревиатуре, которая затем применяется. Например, PKG может быть изменен на PACKAGE, но PA также является аббревиатурой для PINEAPPLE, что означает, что после применения этого изменения конечный результат будет PINEAPPLECKAGE. Каждое сокращение имеет по одному пробелу с каждой стороны, поэтому я решил использовать этот факт, чтобы не обновлять аббревиатуру без пробела с обеих сторон, поэтому в моем коде присутствует CONCAT('% ', @Abbr, ' %'). Тем не менее, когда я пытаюсь этот метод в принципе ничего не меняется. Я смог увидеть ограниченный успех, сняв это ограничение, но тогда возникает другая проблема. Любые идеи относительно того, как я мог бы убедиться, что только вхождения аббревиатур с пробелами по обе стороны рассматриваются и обновляются?
ОБНОВЛЕНИЕ: попробовав несколько решений, опубликованных здесь, я все еще не смог заставить его работать, и я не уверен, почему. Судя по всему это правильно. Вот пример некоторых данных, с которыми я работаю:
JUSTEA HBL PKG CMCL CHM LG LR 1.5OZ
PRIDE OF INDIA BG ASM B BKFST 25 CT
CTL BR H-B 7BLSM PP 1 CT
POSTI H-B HRH CRN 20 CT
DRS H-B EPGP LPLDS PTVP TGN 20 CT
ULTLC BG CHG 100 CT
PG TIPS BG D B 40 CT
RPBL R-B B HLDY FT BLD 6 CT
Это нормально и выглядит так, как будто должно конвертироваться без проблем. Тем не менее, когда я запускаю код с указанными пробелами (как в случае с "LIKE '% ' + @Abbr + ' %'", который был моим первым наклоном), данные остаются полностью неизменными. Если я удаляю их, данные становятся совершенно неразборчивыми. Например, строка, начинающаяся с PRIDE OF INDIA, становится
ГОРДОСТЬ ИНДИИ (N) ИРЛАНДСКИЙ ДЕНЬ ЧЕРНЫЙ AG ASIA PLUM RICOT SPICE(D) СЕРЬЕЗНЫЙ ЧЕРНЫЙ ЧЕРНЫЙ KFST 25 СМЕСЬ И ПОМОЩЬ NT
Мне кажется, я должен отметить, что эти данные изначально были импортированы из таблиц Excel. Есть ли шанс, что это как-то связано с тем, что пробелы не распознаются?
3 ответа
Я думаю, что вам нужно обновлять каждую запись Замененной таблицы несколько раз, и вам нужно учитывать 4 местоположения сокращений (Один, Первый, Посередине, Последний). Что-то вроде этого:
DECLARE @Replaced TABLE ([DescriptionCodes] varchar(50))
DECLARE @Abbreviations TABLE ([Abbrv] varchar(50), [Description] varchar(50))
INSERT INTO @Replaced([DescriptionCodes]) VALUES ('TADIN H-B GR')
INSERT INTO @Replaced([DescriptionCodes]) VALUES ('PKG')
INSERT INTO @Replaced([DescriptionCodes]) VALUES ('PKG PA')
INSERT INTO @Abbreviations([Abbrv], [Description]) VALUES ('H-B', 'HERBAL BAG')
INSERT INTO @Abbreviations([Abbrv], [Description]) VALUES ('GR', 'GREEN')
INSERT INTO @Abbreviations([Abbrv], [Description]) VALUES ('PKG', 'PACKAGE')
INSERT INTO @Abbreviations([Abbrv], [Description]) VALUES ('PA', 'PINAPPLE')
DECLARE @RowCount int;
WHILE 1 = 1
BEGIN
SET @RowCount = 0;
UPDATE r
SET r.[DescriptionCodes] = REPLACE(r.[DescriptionCodes], a.[Abbrv], a.[Description])
FROM @Replaced r join @Abbreviations a ON r.[DescriptionCodes] = a.[Abbrv];
SET @RowCount = @RowCount + @@RowCount;
UPDATE r
SET r.[DescriptionCodes] = REPLACE(r.[DescriptionCodes], ' ' + a.[Abbrv] + ' ', ' ' + a.[Description] + ' ')
FROM @Replaced r join @Abbreviations a ON r.[DescriptionCodes] like '% ' + a.[Abbrv] + ' %';
SET @RowCount = @RowCount + @@RowCount;
UPDATE r
SET r.[DescriptionCodes] = REPLACE(r.[DescriptionCodes], ' ' + a.[Abbrv],' ' + a.[Description])
FROM @Replaced r join @Abbreviations a ON r.[DescriptionCodes] like '% ' + a.[Abbrv];
SET @RowCount = @RowCount + @@RowCount;
UPDATE r
SET r.[DescriptionCodes] = REPLACE(r.[DescriptionCodes], a.[Abbrv] + ' ', a.[Description] + ' ')
FROM @Replaced r join @Abbreviations a ON r.[DescriptionCodes] like a.[Abbrv] + ' %';
SET @RowCount = @RowCount + @@RowCount;
IF @ROWCOUNT = 0 BREAK;
END
SELECT * FROM @Replaced
Зачем использовать "LIKE", если вы собираетесь добавить пробелы? просто делать:
WHERE DescriptionCodes = @Abbr
Вы можете сделать это, и оно достигнет того, что вы пытаетесь сделать:
LIKE '% ' + @Abbr + ' %'