T- SQL: разделение символьных значений между несогласованными экземплярами разделителей - PullRequest
0 голосов
/ 01 мая 2020

Есть строка, сопровождающая значение, которое мне нужно извлечь из столбца. Я могу извлечь значение из большинства строк, но есть несколько случаев, когда значение имеет разные свойства. Это упрощенный пример проблемы:

IF OBJECT_ID('TEMPDB..#TABLE') IS NOT NULL
    DROP TABLE #TABLE

CREATE TABLE #TABLE(
colSTRING           NVARCHAR(MAX)       NULL
);
INSERT INTO #TABLE (colSTRING)
VALUES (',SHOULD NOT BE STORED THIS WAY:22.67')
    ,(',SHOULD NOT BE STORED THIS WAY:46.32')
    ,(',SHOULD NOT BE STORED THIS WAY:23.45')
    ,(',SHOULD NOT BE STORED THIS WAY:66.67')
    ,(',SHOULD NOT BE STORED THIS WAY:22.35,ANOTHER BAD THING:OK')
;
SELECT * FROM #TABLE

Вывод: OUTPUT1

Обратите внимание, что в конце строки справа находится число из ':'. Это число, которое мне нужно извлечь.

Однако нижний ряд показывает, что в той же ячейке есть вторая строковая запись. Мне нужно извлечь 22,35 из этой ячейки, опуская при этом остальную часть строки.

Это то, что у меня есть;

SELECT 
    (RIGHT(colSTRING,CHARINDEX(':',REVERSE(colSTRING))-1)) [STRING NUMBER]
FROM #TABLE

вывод: OUTPUT2

Это работает для других значений в таблице, но нижняя строка не извлекает правильное значение. Она принимает строку справа от ':' второй строковой записи.

Есть ли способ использовать эту логику c только при первом появлении ':'?

1 Ответ

0 голосов
/ 01 мая 2020

Так вот как я решил проблему, благодаря идее @MartinSmith. Я немного скорректировал пример, чтобы показать, как он взаимодействует с числом, состоящим более чем из 2 цифр (> = 100,00).

IF OBJECT_ID('TEMPDB..#TABLE') IS NOT NULL
    DROP TABLE #TABLE

CREATE TABLE #TABLE(
colSTRING           NVARCHAR(MAX)       NULL
);
INSERT INTO #TABLE (colSTRING)
VALUES (',SHOULD NOT BE STORED THIS WAY:22.67')
    ,(',SHOULD NOT BE STORED THIS WAY:46.32')
    ,(',SHOULD NOT BE STORED THIS WAY:23.45')
    ,(',SHOULD NOT BE STORED THIS WAY:766.67')
    ,(',SHOULD NOT BE STORED THIS WAY:22.35,ANOTHER BAD THING:OK')
;
SELECT * FROM #TABLE

Решение: в этом случае каждая запись строки всегда начинается с запятой. Я могу использовать эту информацию в заявлении CASE. Я делаю столбец с заполненными записями для каждого случая, когда есть числа <100,00 или> = 100,00

SELECT ISNULL(CASE WHEN [2DIGITS] LIKE ',%' THEN NULL ELSE [2DIGITS] END,[3DIGITS]) [FIXED]
FROM(
SELECT 
    (RIGHT(colSTRING,CHARINDEX(':',REVERSE(colSTRING))-1)) [STRING NUMBER]
    ,SUBSTRING(colSTRING,1 + PATINDEX('%:[0-9][0-9].[0-9][0-9]%', colSTRING),5) [2DIGITS]
    ,SUBSTRING(colSTRING,1 + PATINDEX('%:[0-9][0-9][0-9].[0-9][0-9]%', colSTRING),6) [3DIGITS]
FROM #TABLE
)A
...