chints786 Ответов: 2

Sql-запрос для сравнения отдельных значений в столбце со строкой с разделителями


Всем Привет,

У меня есть 2 колонки.

Текущее значение
MasterListOfValues

MasterListOfValues - это ';'с разделителями.например значений:- A;B;C;D

Таблица выглядит так:-

current value  MasterListofvalue
A              Aa;B;C;D
B              A;B;C;D
C              A;B;C;D


Теперь для каждого совпадения мы должны сделать еще один столбец с точным совпадением и поместить туда это значение , а если точного совпадения нет, то мы должны создать еще один столбец с аналогичным совпадением.

Выходные данные должны выглядеть следующим образом:-

current value  MasterListofvalue  Exact Match  Similar Match
A              Aa;B;C;D              N/A
B              A;B;C;D                          B
C              A;B;C;D                          C


Пожалуйста, сообщите об этом.

Что я уже пробовал:

Я попытался создать функцию разделения, но не смог получить желаемый результат.

CHill60

Вы должны показать нам код, который не сработал. Кроме того, ваше объяснение не очень понятно. Вы также должны избегать хранения разделенных значений в столбце - это плохой дизайн.
Попробуйте лучше объяснить свою проблему - например, я не понимаю, почему B и C имеют "похожее совпадение", а A-нет. Четко сформулируйте правила.

chints786

Привет,

B и C-это аналогичное совпадение, потому что они являются одним из значений в столбце MasterListof Values. По отношению к A MasterListValue состоит из Aa, следовательно, это не идеальное совпадение, но оно должно быть под аналогичным совпадением, и значение там должно быть A.

Вот эта функция :-

Создайте функцию [dbo].[SplitString]
(
@List NVARCHAR(макс.),
@Delimiter NVARCHAR(255)
)
ТАБЛИЦА ВОЗВРАТОВ
С SCHEMABINDING КАК
ВЕРНУТЬ
С Е1(Н) Как ( выбрать 1 объединить все выбрать 1 объединить все выбрать 1 объединить все выбрать 1
ВСЕСОЮЗНАЯ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1
ВСЕСОЮЗНАЯ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1),
E2(N) AS (выберите 1 из E1 a, E1 b),
E4(N) AS (выберите 1 из E2 a, E2 b),
E42(N) AS (выберите 1 из E4 a, E2 b),
cteTally(Н) Как (выберите 0 объединить все выбрать первые (DATALENGTH(функция isnull(@список,1)))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E42),
cteStart(N1) AS (SELECT t.N+1 FROM cteTally t
Где (подстрока(@List,t.N,1) = @Delimiter или t.N = 0))
Выберите пункт = подстрока(@список, ы.Н1, функция isnull(null, если(функция charindex(@разделитель,@список,ы.Н1),0)-с.Н1,8000))
От cteStart s;
ГО

перекрестное применение с таблицей данных я бы получил разделенные значения столбца Msater одно под другим, чтобы получить точное совпадение.

2 Ответов

Рейтинг:
2

Maciej Los

Если я правильно вас понял...

Я бы посоветовал использовать КТОС[^]. Видеть:

DECLARE @tmp TABLE(CurrentValue NVARCHAR(30), MasterListofvalue NVARCHAR(150))

INSERT INTO @tmp (CurrentValue,  MasterListofvalue)
VALUES('A', 'Aa;B;C;D'),
('B', 'A;B;C;D'),
('C', 'A;B;C;D')


;WITH CTE AS 
(
	--initial query
	SELECT CurrentValue, MasterListofvalue, LEFT(MasterListofvalue, CHARINDEX(';', MasterListofvalue)-1) AS PartOfMasterList,
		RIGHT(MasterListofvalue, LEN(MasterListofvalue) - CHARINDEX(';', MasterListofvalue)) AS Remainder
	FROM @tmp 
	WHERE CHARINDEX(';', MasterListofvalue)>0
	--recursive part
	UNION ALL
	SELECT CurrentValue, MasterListofvalue, LEFT(Remainder, CHARINDEX(';', Remainder)-1) AS PartOfMasterList,
		RIGHT(Remainder, LEN(Remainder) - CHARINDEX(';', Remainder)) AS Remainder
	FROM CTE
	WHERE CHARINDEX(';', Remainder)>0
	UNION ALL
	SELECT CurrentValue, MasterListofvalue, Remainder AS PartOfMasterList, NULL AS Remainder
	FROM CTE
	WHERE CHARINDEX(';', Remainder)=0
)
SELECT CurrentValue, MasterListofvalue, COALESCE(MAX(ExactMatch), 'N/A') AS ExactMatch, MAX(SimilarMatch) AS SimilarMatch
FROM (
	SELECT t.*, CASE WHEN c.MasterListofvalue = t.CurrentValue THEN t.CurrentValue ELSE NULL END AS ExactMatch,
		CASE WHEN c.PartOfMasterList = t.CurrentValue THEN t.CurrentValue ELSE NULL END AS SimilarMatch, c.PartOfMasterList
	FROM @tmp as t
		LEFT JOIN CTE AS c ON c.CurrentValue = t.CurrentValue
) AS Final
GROUP BY CurrentValue, MasterListofvalue
ORDER BY CurrentValue


Результат:
CurrentValue	MasterListofvalue	ExactMatch	SimilarMatch
A				Aa;B;C;D			N/A			NULL
B				A;B;C;D				N/A			B
C				A;B;C;D				N/A			C


chints786

Спасибо Мацей Лос, однако в этом есть пробел.

Когда текущее значение равно а, нам нужно будет проверить каждое значение в соответствующем мастер-списке значений и проверить, получаем ли мы в нем фактическое "а". В этом случае мы не получим, потому что в нем есть "АА". Таким образом, точное совпадение является ложным или NA.

Однако, когда мы проходим для аналогичного совпадения, своего рода подобное предложение " а "будет совпадать с "АА", и, следовательно, подобное совпадение должно иметь " а " в нем, то есть частичное совпадение.

Аналогично и для других значений.

Надеюсь, вы понимаете.

Maciej Los

Вы пробовали мое решение? Похоже, что нет.
Взгляните на результат, возвращаемый моим кодом. Как вы видите, нет точного соответствия для любого текущего значения. Нет даже похожего соответствия для "АА".

chints786

Я действительно пытался это сделать,и это то, что я пытаюсь понять.

A при сопоставлении с 'Aa,B,C' должен давать 'N/A' в столбце точного соответствия и только 'A' в столбце аналогичного соответствия.

Другим примером может быть

'Щетки' в сочетании с 'кисть';'Бру на' тогда точно матч будет "н/д", но подобный матч будет "кисть".

Как только вы получите точное совпадение с текущим значением, нам не нужно будет искать для него аналогичное совпадение.

Maciej Los

Что ж...
Выходные данные, возвращаемые CTE, точно такие же, как и выходные данные, разработанные вами. Если вы хотите что-то изменить, не стесняйтесь.
Обратите внимание, что CTE разбивает значения MasterListofvalue на части на [;]. Таким образом, запрос, возвращаемый CTE, используется с исходными данными для получения общих частей.

...
FROM @tmp as t
		LEFT JOIN CTE AS c ON c.CurrentValue = t.CurrentValue
...

Это место, где магия проникает в реальность.

Рейтинг:
0

Sayee Subramania Sastry

The following select statement will give you the result, Similarly you can use the update statements to get desired columns 

select * from test where MasterListofvalue > "%"+current_value +"%"


CHill60

Это не сработает. Он будет совпадать на " АА " для "А", что, по словам ОП, неверно