使用多个分隔符

时间:2016-04-28 20:44:24

标签: sql-server tsql parsing

我在SO上找到了一些相关的例子,但没有特别针对这个案例。这是:

我需要使用SQL来解析来自管道分隔的平面文件的数据。其中一个字段的子格式如下。我的结束状态是对字段内的整数求和,但我的问题是看看如何使用SQL SELECT来解析/提取整数。子格式的模式总是在所需的整数前面有一个波浪号(〜),后面跟一个星号(*)。子字段的数量也可能不同(我的例子有5个,但可能更多或更少)。 4 char TAG名称并不重要。

所以这是一个示例:

|GADS~55.0*BILK~0.0*BOBB~81.0*HETT~32.0*IGGR~51.0|

从这个例子中,我想要处理的所有内容都是最终的数字219.再一次,我可以将sum部分作为进一步的步骤;只是对获得数字感兴趣。

我知道如何使用UNIX工具(即AWK,sed等)轻松处理这个问题,而不是在SQL中。任何建议都会有帮助!谢谢!

4 个答案:

答案 0 :(得分:1)

这是你想要的(计算总和219)?对于丑陋的格式很抱歉,但是你肯定可以做到这一点"漂亮"你自己。

declare @Input varchar(255),
        @InputModified varchar(255)

set @Input = '|GADS~55.0*BILK~0.0*BOBB~81.0*HETT~32.0*IGGR~51.0|'


 SELECT 
@InputModified = 
 (
     CAST(CAST((
            SELECT SUBSTRING(@Input, Number, 1)
            FROM master..spt_values
            WHERE Type='p' AND Number <= LEN(@Input) AND
            (
                SUBSTRING(@Input, Number, 1) LIKE '[0-9]' 
                or
                SUBSTRING(@Input, Number, 1) LIKE '~'
                or
                SUBSTRING(@Input, Number, 1) LIKE '.'
            )
            FOR XML Path(''))
        AS xml) AS varchar(MAX))
)


select sum(cast(Integers as float))
from
(
    SELECT 
    LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Integers
    FROM
    (
        SELECT  CAST('<XMLRoot><RowData>' + REPLACE(@InputModified,'~','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
    )t
    CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
) Integers
where IsNumeric(Integers.Integers) = 1

答案 1 :(得分:1)

这将回到219:

  • 在Cut1中,我让字符串以第一个数字开头。
  • 在Cut2中,我剪切了最后一根管子并添加了一个星号
  • 在Splitted中,我将〜替换为XML标签,从而轻松拆分字符串
  • 在最后选择中,纯数字总结了......

现在代码

adjustColumnHeight();

$(window).resize(function(){
    adjustColumnHeight()
});

var adjustColumnHeight = function() {

    // Set height of both columns to auto

    // Find height of each column

    // Set both columns to the height of the tallest column
};

答案 2 :(得分:0)

使用递归cte的其他方法:

DECLARE @Input VARCHAR(255) 
SET @Input = '|GADS~55.0*BILK~0.0*BOBB~81.0*HETT~32.0*IGGR~51.0|'
;WITH cte ( n )
       AS ( SELECT   n = 1
            UNION ALL
            SELECT   n + 1
            FROM     cte
            WHERE    n <= LEN(@Input)
           )

 SELECT  SUM(CONVERT(FLOAT, val))
 FROM   (SELECT SUBSTRING(STUFF(@Input, 1, t.n, ''), 1,
                                PATINDEX('%[*|]%', STUFF(@Input, 1, t.n, '')) - 1) AS Val
         FROM cte AS t
         WHERE SUBSTRING(@Input, t.n, 
                         PATINDEX('%[*|]%', SUBSTRING(@Input, t.n, 99))) LIKE '~%[*|]'
         ) AS T

测试是 HERE

答案 3 :(得分:0)

我试图与众不同。我也没有遵循任何分隔符。 因此,不遵循任何分隔符可能是这种技术的优势。

我只是从字符串中提取第一个数字,然后将字符串从0删除到该数字,依此类推。

所以很明显我们可以使用递归CTE,while循环和使用row_number。

在这里,我尝试使用可能无法优化的递归CTE,但有时候变得很有趣。

func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
    jar.Lock()
    if _, ok := jar.cookies[u.Host]; ok {
        for _, c := range cookies {
            jar.cookies[u.Host] = append(jar.cookies[u.Host], c)
        }
    } else {
        jar.cookies[u.Host] = cookies
    }
    jar.Unlock()
}

这条线对我有用,

DECLARE @Input VARCHAR(255) 
SET @Input = '|GADS~55.0*BILK~0.0*BOBB~81.0*HETT~32.0*IGGR~51.0|';

完整的脚本,

select Left(SubString(@Input, PatIndex('%[0-9.]%', @Input),8000),
PatIndex('%[^0-9.]%', SubString(@Input, 
PatIndex('%[0-9.]%', @Input), 8000) )-1)