Это действительно ужасно, действительно ужасно.Я ни на секунду не предлагаю делать это в вашей РСУБД, и на самом деле я предлагаю вам исправить ваши данные.Вам не следует хранить данные с разделителями (я использую это слово для описания ваших данных) в таблицах, в которых вы должны хранить отдельные столбцы и строки.В этом случае первый «код» должен быть в одном столбце с отношением один ко многим с другой таблицей с кодами, которые вы пытаетесь извлечь.
Поскольку вы не пометили или не упомянули свою версиюSQL Server я использовал последний синтаксис SQL Server.STRING_SPLIT
доступно в SQL Server 2016+ и STRING_AGG
в 2017+.Если вы не используете эти версии, вам нужно заменить эти функции подходящей альтернативой (я предлагаю delimitedsplit8k(_lead)
и FOR XML PATH
соответственно).
В любом случае, что это делает.Во-первых, нам нужно исправить эти данные на что-то более полезное, поэтому я заменяю двойные дефисы (--
) на трубу (|
), так как в ваших данных этого нет.Затем используйте этот канал, чтобы разделить ваши данные на части (отдельные коды).
Поскольку ваш разделитель непоследователен (он не имеет одинаковой ширины), в результате некоторые коды будут иметь начальный дефис, поэтому мне нужноизбавиться от этого.Затем я использую мой ответ на ваш другой вопрос , чтобы разбить код дальше на его компоненты и обратить обратно WHERE
;Раньше ответ искал «плохие» строки, где, как и сейчас, мы хотим «хорошие» строки.
Затем, после всего этого, это так же «просто», как использование STRING_AGG
для разграничения «хороших» строк.:
SELECT STRING_AGG(ca.Code,',') AS Codes
FROM (VALUES('3/1151---------366-500-2570533-1'),
('9/6809---------------------368-510-1872009-1'),
('1-260752-305-154----------------154-200-260752-1--------154-800-13557-1'),
('2397/35425---------------------------------377-500-3224575-1'),
('17059----------------377-500-3263429-1'),
('126/42906---------------------377-500-3264375-1'),
('2269/2340-------------------------377-500-3065828-1'),
('2267/767---------377-500-1452908-4'),
('2395/118593---------377-500-3284699-1'),
('2395/136547---------377-500-3303413-1'),
('92/10260---------------------------377-500-1636038-1'),
('2345-2064---------377-500-3318493-1'),
('365-2290--------377-500-3278261-12'),
('365-7212--------377-500-2587120-1')) V(Codes)
CROSS APPLY (VALUES(REPLACE(V.Codes,'--','|'))) D(DelimitedCodes)
CROSS APPLY STRING_SPLIT(D.DelimitedCodes,'|') SS
CROSS APPLY (VALUES(CASE LEFT(SS.[value],1) WHEN '-' THEN STUFF(SS.[value],1,1,'') ELSE SS.[value] END)) ca(Code)
CROSS APPLY (VALUES(PARSENAME(REPLACE(ca.Code,'-','.'),4),
PARSENAME(REPLACE(ca.Code,'-','.'),3),
PARSENAME(REPLACE(ca.Code,'-','.'),2),
PARSENAME(REPLACE(ca.Code,'-','.'),1))) PN(P1, P2, P3, P4)
WHERE LEN(PN.P1) = 3
AND LEN(PN.P2) = 3
AND LEN(PN.P3) BETWEEN 5 AND 7
AND LEN(PN.P4) BETWEEN 1 AND 2
AND ca.Code NOT LIKE '%[^0-9\-]%' ESCAPE '\'
GROUP BY V.Codes;
дБ <> скрипка