Вставить часть одной строки в другую строку в заданной позиции

У меня есть эти столбцы в SQL Server

LineNumber                           DocumentNumber
1.1/2-GM-100-10026-G01-N-1-1001      DW-2224-100-1330-1001

10-FW-130-13576-B90-N-1-100-1001     DW-2224-100-1330-1001

4-IA-160-12325-B10-N-1-2001          DW-2224-160-1330-2001

UG-12-CS-160-160CMH306-B93-N-1-1062  DW-2224-160-1433-1062

24-SL-160-12116-B12-H-1-160-MMP          DW-2224-160-1433-1062

Я хочу обновить linenumber основывается на documentnumber Я хочу просто добавить третью часть documentnumber я имею в виду экс "100,160,100 и т. д." добавить в мой line number до последней части я имею в виду 2001,1001 результат, который я ожидал:

LineNumber                                    DocumentNumber
1.1/2-GM-100-10026-G01-N-1-100-1001           DW-2224-100-1330-1001

10-FW-130-13576-B90-N-1-100-1001              DW-2224-100-1330-1001

4-IA-160-12325-B10-N-1-160-2001               DW-2224-160-1330-2001

UG-12-CS-160-160CMH306-B93-N-1-160-1062       DW-2224-160-1433-1062

24-SL-160-12116-B12-H-1-160-MMP               DW-2224-160-1433-1062

Третья часть документа добавлена ​​к белью. Но у некоторых белья есть эта часть, и ее не следует добавлять.

Я хочу обновить его на сервере sql.

\SELECT  [Id]
      ,[LineNumber]
      ,[DocumentNumber]

  FROM [SPMS2].[dbo].[Lines]

ОБНОВИТЬ

Это результат ответа @Shnugo. Но, как вы видите, часть уже существует в некоторых случаях. После вставок эта часть удваивается, но мне они нужны только один раз!

3 ответа

Решение

Извините, этот дизайн ужасен... Если вам нужна такая строка, она должна быть встроена в секунду, если она вам нужна в соответствии с некоторыми бизнес-правилами из правильных частей. Вы должны действительно нормализовать это!

Но если вам нужно придерживаться этого, попробуйте это так:

DECLARE @tbl TABLE(LineNumber VARCHAR(100),DocumentNumber VARCHAR(100));
INSERT INTO @tbl VALUES
 ('1.1/2-GM-100-10026-G01-N-1-1001','DW-2224-100-1330-1001')
,('10-FW-130-13576-B90-N-1-100-1001','DW-2224-100-1330-1001')
,('4-IA-160-12325-B10-N-1-2001','DW-2224-160-1330-2001')
,('UG-12-CS-160-160CMH306-B93-N-1-1062','DW-2224-160-1433-1062')
,('24-SL-160-12116-B12-H-1-160-MMP','DW-2224-160-1433-1062');

SELECT STUFF(LineNumber
             ,LEN(LineNumber)-CHARINDEX('-',REVERSE(LineNumber)) + 1
             ,0
             ,'-' + CAST('<x>' + REPLACE(DocumentNumber,'-','</x><x>') + '</x>' AS XML).value('/x[3]','varchar(max)'))
FROM @tbl AS tbl

Это результат

1.1/2-GM-100-10026-G01-N-1-100-1001
10-FW-130-13576-B90-N-1-100-100-1001
4-IA-160-12325-B10-N-1-160-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062
24-SL-160-12116-B12-H-1-160-160-MMP     --Here the 160 is twice due to the test data...

Приведение к XML позволяет легко выбирать третью часть вашего DocumentNumber (но следует помнить о запрещенных символах, таких как <, > and & и еще немного). STUFF функция помещает эту строку в правильную позицию (первый дефис в обратной строке)

ОБНОВИТЬ

Согласно вашему комментарию, этот новый запрос сначала извлечет обе части и сравнит их. Вставка происходит только в том случае, если вторая последняя часть в номере строки не равна третьей части в DocumentNumber

SELECT CASE WHEN SecondLastInLineNumber=ThirdInDocumentNumber THEN LineNumber
       ELSE
        STUFF(LineNumber
             ,LEN(LineNumber)-CHARINDEX('-',REVERSE(LineNumber)) + 1
             ,0
             ,'-' + ThirdInDocumentNumber)
       END AS NewLineNumber
FROM @tbl AS tbl
CROSS APPLY
(
    SELECT REVERSE(CAST('<x>' + REPLACE(REVERSE(LineNumber),'-','</x><x>') + '</x>' AS XML).value('/x[2]','varchar(max)'))
          ,CAST('<x>' + REPLACE(DocumentNumber,'-','</x><x>') + '</x>' AS XML).value('/x[3]','varchar(max)')
) AS Parts(SecondLastInLineNumber,ThirdInDocumentNumber)

Результат

1.1/2-GM-100-10026-G01-N-1-100-1001
10-FW-130-13576-B90-N-1-100-1001
4-IA-160-12325-B10-N-1-160-2001
UG-12-CS-160-160CMH306-B93-N-1-160-1062
24-SL-160-12116-B12-H-1-160-MMP

Однако решение, данное @Shnugo, является хорошим.

Тем не менее вы можете попробовать ниже вариант.

Создайте одну функцию, которая разделяет данные по заданному символу, как показано ниже:

CREATE FUNCTION [dbo].[fnSplit]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
            FROM Split
            WHERE endpos > 0
    )
    SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
    FROM Split
)

Теперь, используйте ниже выберите заявление

SELECT REPLACE
(
    LineNumber,
    '-'+ REVERSE(Substring(REVERSE(LineNumber),0, charindex('-',REVERSE(LineNumber)))),
    '-'+
    (
        SELECT Data FROM [dbo].[fnSplit] (DocumentNumber,'-') Where Id=3
    )+'-'+ REVERSE(Substring(REVERSE(LineNumber),0, charindex('-',REVERSE(LineNumber))))
)
FROM TableName
CREATE TABLE [dbo].[Doc](
       [id] [int] IDENTITY(1,1) NOT NULL,
       [LineNumber] [varchar](200) NULL,
       [DocumentNumber] [varchar](200) NULL
) ON [PRIMARY]

GO
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('1.1/2-GM-100-10026-G01-N-1-1001','DW-2224-100-1330-1001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('10-FW-130-13576-B90-N-1-100-1001','DW-2224-100-1330-1001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('4-IA-160-12325-B10-N-1-2001','DW-2224-160-1330-2001')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('UG-12-CS-160-160CMH306-B93-N-1-1062','DW-2224-160-1433-1062')
INSERT INTO [Doc] ([LineNumber],[DocumentNumber])VALUES('24-SL-160-12116-B12-H-1-160-MMP','DW-2224-160-1433-1062')
GO
SELECT
  Id,
  DocumentNumber,
  LineNumber,
  REVERSE(STUFF(REVERSE(LineNumber), CHARINDEX('-', REVERSE(LineNumber)) + 1, 0, REVERSE(REVERSE(REVERSE('-' + SUBSTRING(DocumentNumber, 9, LEN(DocumentNumber) - 18)))))) 
              AS LineNumberInRequiredFormat
FROM [Doc]


    Result
    LineNumberInRequiredFormat
    *********************************
    1.1/2-GM-100-10026-G01-N-1-100-1001
    10-FW-130-13576-B90-N-1-100-100-1001
    4-IA-160-12325-B10-N-1-160-2001
    UG-12-CS-160-160CMH306-B93-N-1-160-1062
    24-SL-160-12116-B12-H-1-160-160-MMP
Другие вопросы по тегам