【问题标题】:Dynamic extraction of multiple text from a single row - SQL从单行动态提取多个文本 - SQL
【发布时间】:2019-02-14 17:13:55
【问题描述】:

表格中的数值格式如下

Returns Request for Order: 121212, RA Number:1654356, 4 Products:, 1 x "ABC" (11169595), Expected Action: Replace, 1 x "FGH" (11449119), Expected Action: Refund, 1 x "XCV" (11100873), Expected Action: Refund, 1 x "VVV" (11028561), Expected Action: Refund 
-------------------------------------------------------------------------------------------------------------------------------
Returns Request for Order: 234354, RA Number:3465646, 3 Products:, 3 x "FGH" (11449119), Expected Action: Replace 
-----------------------------------------------------------------------------------------------------
Returns Request for Order: 234355, RA Number:3465646, 3 Products:, 2 x "ABC" (11169595),  Expected Action: Replace, 1 x "FGH" (11449119), Expected Action: Refund 

以下是所需的o/p格式:

 Order_Num        REFUND_PRODUCTS                 REPLACE_PRODUCTS
 121212     11449119,11100873,11028561           11169595
 234354                                  11449119,11449119,11449119
 234355         11449119                       11169595,11169595

如果它的 '2 x "ABC" (11169595) 预期操作:REPLACE',那么在 REPLACE_PRODUCT 列下,数字 11169595' 应该出现两次。

如果它是“3 x ....”,那么三次。 REFUND_PRODUCT 类似

我该怎么办?

【问题讨论】:

  • 你肯定有一个挑战。您可以为示例数据发布创建表语句和插入语句吗?我不确定您发布的是单行还是多行。
  • 单行。 '-------' 表示下一行。
  • 哎呀!!!你有机会修复数据结构吗?这将很难解开。
  • 我已经更新了...它在单行中
  • 哇,这真是太糟糕了。您将需要一个保持序号位置的字符串拆分器。 Here 是我所知道的唯一一个基于集合的集合,它返回输出中的位置。但这并没有触及到这将是多么困难的表面。

标签: sql sql-server regex substring extraction


【解决方案1】:

好的,只要您的格式保持一致,您就可以使用子字符串和 here 找到的函数的修改版本。我在这里创建了一个快速计数表,但如果您已经有一个计数表或数字表要使用,您可以将其换掉。

正如 Sean 在 cmets 中提到的,如果这是一张大桌子,这将需要一段时间才能运行。我不认为真的有任何方法可以解决这个问题,因为这是一个切弦练习。

Declare @mytable as table (mydata varchar(4000))

Declare @myresults as table (order_num int,  refund_products varchar(1000), replace_products varchar(1000))

declare @tally as table (t_idx int)
insert into @tally
select 1 UNION ALL
select 2 UNION ALL
select 3 UNION ALL
select 4 UNION ALL
select 5 UNION ALL
select 6 UNION ALL
select 7 UNION ALL
select 8 UNION ALL
select 9

INSERT INTO @mytable
Select 'Returns Request for Order: 121212 RA Number:1654356 4 Products: 1 x "ABC" (11169595) Expected Action: REPLACE 1 x "FGH" (11449119) Expected Action: REFUND 1 x "XCV" (11100873) Expected Action: REFUND 1 x "VVV" (11028561) Expected Action: REFUND' UNION ALL
Select 'Returns Request for Order: 234354 RA Number:3465646 3 Products: 3 x "FGH" (11449119) Expected Action: REPLACE' UNION ALL
Select 'Returns Request for Order: 234355 RA Number:3465646 3 Products: 2 x "ABC" (11169595)  Expected Action: REPLACE 1 x "FGH" (11449119) Expected Action: REFUND'

insert into @myresults
Select
substring(mydata,charindex('Order:',mydata, 0)+7,6),
substring(
        STUFF(
            (Select ',' + pos_string from dbo.FindPatternLocation(mydata,'(') FOR XML PATH('')),1,1,'' ) ,10,500),

STUFF(
        (Select ',' + substring(mydata ,charindex('(',mydata,0)+1,8) from @tally where t_idx<=substring(mydata,charindex('(',mydata,0)-10,1) FOR XML PATH('')),1,1,''
        )

from @mytable

Select * from @myresults

功能:

CREATE FUNCTION dbo.FindPatternLocation
(
    @string NVARCHAR(MAX),
    @term   NVARCHAR(255)
)
RETURNS TABLE
AS
    RETURN 
    (
      SELECT pos = Number - LEN(@term) ,

      substring(@string, Number - LEN(@term)+1, 8) as pos_string

      FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(@string, Number, 
      CHARINDEX(@term, @string + @term, Number) - Number)))
      FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
      FROM sys.all_objects) AS n(Number)
      WHERE Number > 1 AND Number <= CONVERT(INT, LEN(@string)+1)
      AND SUBSTRING(@term + @string, Number, LEN(@term)) = @term
    ) AS y);

作为函数的替代,您可以将其用作第二列:-

substring(
        STUFF(
            (Select ',' + pos_string from 

             (SELECT pos = Number - LEN('(') ,
              substring(mydata, Number - LEN('(')+1, 8) as pos_string

      FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(mydata, Number, 
      CHARINDEX('(', mydata + '(', Number) - Number)))
      FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
      FROM sys.all_objects) AS n(Number)
      WHERE Number > 1 AND Number <= CONVERT(INT, LEN(mydata)+1)
      AND SUBSTRING('(' + mydata, Number, LEN('(')) = '('
    ) aa) bb  FOR XML PATH('')),1,1,'' ) ,10,500)

【讨论】:

  • 这真的很接近。 OP 说他们希望在替换列中有一个逗号分隔的列表,其中的数字重复次数与它所说的产品一样多。另一个加入到计数表的另一个东西应该得到它。我当然希望 OP 使用的表不是很大。
  • 是的 - 我很着急。忘记添加使用计数列来计算和乘以替换列的位
  • 修改了脚本以提供 OP 要求的内容。
  • 感谢@iainc!。有没有办法将函数合并到主代码中?
  • 不要在 cmets 中放代码,它根本不会格式化。如果您需要在答案中添加一些详细信息,您应该编辑您的答案。
猜你喜欢
  • 1970-01-01
  • 2018-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多