Нахождение совпадающих значений в поле, разделенном пробелами - PullRequest
0 голосов
/ 11 февраля 2019

В SQL Server у меня есть поле с разделителями данных (по пробелам) в нем.

Например,

recid| Delimited data field
1| 1 2 3 4 5
2| 1 2 3 3 5
3| 1 1 1 1 1

Мне нужно перебрать все записи в БД и опроситьполе данных с разделителями и сравните третью и четвертую части данных друг с другом, и, если они совпадают, верните recid и все поле с разделителями.

Итак, из моего примера записи 2 и 3 имеют совпадающие части данных, поэтомуон вернет: -

2|1 2 3 3 5
3|1 1 1 1 1

Поскольку 3 3 совпадения, как и 1 1.

Спасибо.

Ответы [ 6 ]

0 голосов
/ 11 февраля 2019

Просто для удовольствия, вроде сумасшедшего кодирования:

DECLARE @Table Table (
    recid               INT,
    DelimitedDataField  VARCHAR(32)
)

INSERT @Table (recid, DelimitedDataField)
VALUES
    (1, '1 2 3 4 5'),
    (2, '1 2 3 3 5'),
    (3, '1 1 1 1 1')

SELECT *
FROM @Table
WHERE
SUBSTRING (
    STUFF(
        STUFF(
            DelimitedDataField + ' - - -',
            1,
            CHARINDEX(' ', DelimitedDataField + ' - - -'),
            ''
        ),
        1,
        CHARINDEX(' ', STUFF(
                        DelimitedDataField + ' - - -',
                        1,
                        CHARINDEX(' ', DelimitedDataField + ' - - -'), '')
                 ),
        ''),
    1,
    CHARINDEX(' ', STUFF(
        STUFF(
            DelimitedDataField + ' - - -',
            1,
            CHARINDEX(' ', DelimitedDataField + ' - - -'),
            ''
        ),
        1,
        CHARINDEX(' ', STUFF(
                        DelimitedDataField + ' - - -',
                        1,
                        CHARINDEX(' ', DelimitedDataField + ' - - -'), '')
                 ),
        '')
        )
) = 
SUBSTRING (
        STUFF(
            STUFF(
                STUFF(
                    DelimitedDataField + ' - - -',
                    1,
                    CHARINDEX(' ', DelimitedDataField + ' - - -'),
                    ''
                ),
                1,
                CHARINDEX(' ', STUFF(
                                DelimitedDataField + ' - - -',
                                1,
                                CHARINDEX(' ', DelimitedDataField + ' - - -'), '')
                         ),
                ''),
            1,
            CHARINDEX(' ', STUFF(
                STUFF(
                    DelimitedDataField + ' - - -',
                    1,
                    CHARINDEX(' ', DelimitedDataField + ' - - -'),
                    ''
                ),
                1,
                CHARINDEX(' ', STUFF(
                                DelimitedDataField + ' - - -',
                                1,
                                CHARINDEX(' ', DelimitedDataField + ' - - -'), '')
                         ),
                '')
            ),
            ''
        ),
        1,
        CHARINDEX(' ',      STUFF(
            STUFF(
                STUFF(
                    DelimitedDataField + ' - - -',
                    1,
                    CHARINDEX(' ', DelimitedDataField + ' - - -'),
                    ''
                ),
                1,
                CHARINDEX(' ', STUFF(
                                DelimitedDataField + ' - - -',
                                1,
                                CHARINDEX(' ', DelimitedDataField + ' - - -'), '')
                         ),
                ''),
            1,
            CHARINDEX(' ', STUFF(
                STUFF(
                    DelimitedDataField + ' - - -',
                    1,
                    CHARINDEX(' ', DelimitedDataField + ' - - -'),
                    ''
                ),
                1,
                CHARINDEX(' ', STUFF(
                                DelimitedDataField + ' - - -',
                                1,
                                CHARINDEX(' ', DelimitedDataField + ' - - -'), '')
                         ),
                '')
            ),
            ''
        ))
)

AND SUBSTRING (
    STUFF(
        STUFF(
            DelimitedDataField + ' - - -',
            1,
            CHARINDEX(' ', DelimitedDataField + ' - - -'),
            ''
        ),
        1,
        CHARINDEX(' ', STUFF(
                        DelimitedDataField + ' - - -',
                        1,
                        CHARINDEX(' ', DelimitedDataField + ' - - -'), '')
                 ),
        ''),
    1,
    CHARINDEX(' ', STUFF(
        STUFF(
            DelimitedDataField + ' - - -',
            1,
            CHARINDEX(' ', DelimitedDataField + ' - - -'),
            ''
        ),
        1,
        CHARINDEX(' ', STUFF(
                        DelimitedDataField + ' - - -',
                        1,
                        CHARINDEX(' ', DelimitedDataField + ' - - -'), '')
                 ),
        '')
        )
) <>'-'
0 голосов
/ 11 февраля 2019

Если у вас SQL Server 2016 или выше, вы можете попробовать один подход, используя OPENJSON() для разделения ваших входных данных.Важной частью здесь является тот факт, что когда OPENJSON анализирует массив JSON, индексы элементов в тексте JSON возвращаются как ключи (на основе 0).

Ввод:

CREATE TABLE #Table (
   RecId int,
   Data varchar(max)
)
INSERT INTO #Table
   (RecId, Data)
VALUES 
   (1, '1 2 3 4 5'),
   (2, '1 2 3 3 5'),
   (3, '1 1 1 1 1')

Заявление:

SELECT 
   t.RecId,
   t.Data
FROM #Table t
CROSS APPLY (SELECT [value] FROM OPENJSON('["' +  REPLACE(t.Data,' ','","') + '"]') WHERE [key] = 2) j3
CROSS APPLY (SELECT [value] FROM OPENJSON('["' +  REPLACE(t.Data,' ','","') + '"]') WHERE [key] = 3) j4
WHERE j3.[value] = j4.[value]

Вывод:

RecId   Data
2       1 2 3 3 5
3       1 1 1 1 1
0 голосов
/ 11 февраля 2019

Вот еще одно решение этой проблемы.

Я настроил функцию разделения в этой ссылке ( T-SQL: напротив конкатенации строк - как разбить строку на несколько записей ) aнемного, чтобы сделать его полезным в вашем сценарии.

Вот функция.

CREATE FUNCTION dbo.SplitAndGetNumberAt (@sep char(1), @s varchar(512), @pos int)
RETURNS INT
BEGIN
declare @val as varchar(10);

WITH Pieces(pn, start, stop) AS (
    SELECT 1, 1, CHARINDEX(@sep, @s)
    UNION ALL
    SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
    FROM Pieces
    WHERE stop > 0
)
SELECT @val = SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END)
FROM Pieces where pn = @pos;

RETURN @val
END

Теперь вы можете использовать эту функцию, чтобы получить 3-ю и 4-ю позиции чисел и легко сравнивать.

select recid, deldata
from so1
where dbo.SplitAndGetNumberAt (' ', deldata, 3) = dbo.SplitAndGetNumberAt (' ', deldata, 4)

Надеюсь, это поможет.

0 голосов
/ 11 февраля 2019

Ваш вопрос состоит из двух частей, найдите n-й раздел и затем сравните.Ваш первый подход должен решить проблему, пока вы не найдете встроенные функции, которые могут выполнить эту работу.Вот один метод внутреннего запроса, возвращающий результат после разделения и внешнего сравнения:

SELECT recid,Delimited from (
        SELECT recid,Delimited, SUBSTRING(Delimited, 
              charindex(' ', Delimited, (charindex(' ', Delimited, 1))+2)+1,1) 
              third, SUBSTRING(Delimited, charindex(' ',Delimited, 
              (charindex(' ', Delimited, 1))+3)+1,1) 
              fourth FROM YourTable) tr
        WHERE third = fourth

См. простые substring и charindex могут выполнить эту работу.

0 голосов
/ 11 февраля 2019

Необходимо разделить данные, дать номер строки и затем сравнить.

Схема:

SELECT *  INTO #TAB FROM (
SELECT 1, '1 2 3 4 5' UNION ALL
SELECT 2, '1 2 3 3 5' UNION ALL
SELECT 3, '1 1 1 1 1'  
)A (recid , Delimited_data_field)

Решение:

;WITH CTE
AS (
    SELECT recid
        ,Delimited_data_field
        ,ROW_NUMBER() OVER (PARTITION BY recid ORDER BY (SELECT 1)) RNO
        ,splt.X.value('.', 'INT') VAL
    FROM (
        SELECT recid
            ,Delimited_data_field
            ,CAST('<M>' + REPLACE(Delimited_data_field, ' ', '</M><M>') + '</M>' AS XML) DATA
        FROM #TAB
        ) A
    CROSS APPLY A.DATA.nodes('/M') splt(x)
    )
SELECT C.recid
    ,C2.Delimited_data_field
FROM CTE C
INNER JOIN CTE C2 ON C.recid = C2.recid AND C.RNO = 3 AND C2.RNO = 4
AND C.VAL = C2.VAL 

Результат:

recid   Delimited_data_field
2       1 2 3 3 5
3       1 1 1 1 1
0 голосов
/ 11 февраля 2019

Если это всегда 1 цифра и один и тот же формат, вы можете попробовать выполнить следующее:

select * from @table
where SUBSTRING([data], 5, 1) = SUBSTRING([data], 7, 1)

Если нет (числа не однозначные), вы можете попробовать выполнить следующее.

Демоверсия

...