添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

该值由一个 "S "和/或一个 "L "组成,每个字母后面都有一个数字。 我需要写一个查询,它将返回两列,"S "和 "L",其中只有字母后面有对应的数字值。
上面的例子应该是这样的。

S         L  
======== ==========
0 100000
0 50
10 0
15 10
20 0
90 0
10 0
10 5
10 40
10 5

如果没有找到 "S "或 "L",默认值为零。

2 个评论
是否有什么原因,为什么这些东西不首先插入单独的列中? 创建一个计算列,把它们放回一起,比写一个函数来解析和提取这些值要容易得多。
我正在从一个......让我们称之为 "有趣 "的......传统数据库中导入数据,开发人员选择将多个值存储在一个单一的nvarchar列。我正试图清理它,并在导入程序中把数据分成不同的列。
sql-server
tsql
sql-server-2008
Jakob Gade
Jakob Gade
发布于 2010-02-24
4 个回答
KM.
KM.
发布于 2010-02-24
已采纳
0 人赞同

试试这个。

DECLARE @YourTable table (RowValue varchar(30))
INSERT INTO @YourTable VALUES ('L100000')
INSERT INTO @YourTable VALUES ('L50')
INSERT INTO @YourTable VALUES ('L5')
INSERT INTO @YourTable VALUES ('S10')
INSERT INTO @YourTable VALUES ('S15L10')
INSERT INTO @YourTable VALUES ('S20')
INSERT INTO @YourTable VALUES ('S90')
INSERT INTO @YourTable VALUES ('S10')
INSERT INTO @YourTable VALUES ('S10L5')
INSERT INTO @YourTable VALUES ('S10L40')
INSERT INTO @YourTable VALUES ('S10L5')
SELECT
WHEN LocationS>0 AND LocationL=0 THEN RIGHT(RowValue,Length-1)
        WHEN LocationS>0 THEN SUBSTRING(RowValue,2,LocationL-2)
        ELSE NULL
END AS S
    ,CASE
WHEN LocationS=0 AND LocationL>0 THEN RIGHT(RowValue,Length-1)
         WHEN LocationS>0 AND LocationL>0 THEN RIGHT(RowValue,Length-LocationL)
         ELSE NULL
END AS L
    ,RowValue
    FROM (SELECT
              RowValue
                  ,CHARINDEX('S',RowValue) AS LocationS
                  ,CHARINDEX('L',RowValue) AS LocationL
                  ,LEN(RowValue) AS Length
              FROM @YourTable
S                              L                              RowValue
------------------------------ ------------------------------ --------------
NULL 100000                         L100000
NULL 50                             L50
NULL 5                              L5
10 NULL                           S10
15 10                             S15L10
20 NULL                           S20
90 NULL                           S90
10 NULL                           S10
10 5                              S10L5
10 40                             S10L40
10 5                              S10L5
(11 row(s) affected)

如果你有大量的数据,可以试试这个,它可能更快(有相同的输出,基本上去掉了派生表,让所有东西都使用内联函数)。

SELECT
WHEN CHARINDEX('S',RowValue)>0 AND CHARINDEX('L',RowValue)=0 THEN RIGHT(RowValue,LEN(RowValue)-1)
        WHEN CHARINDEX('S',RowValue)>0 THEN SUBSTRING(RowValue,2,CHARINDEX('L',RowValue)-2)
        ELSE NULL
END AS S
    ,CASE
WHEN CHARINDEX('S',RowValue)=0 AND CHARINDEX('L',RowValue)>0 THEN RIGHT(RowValue,LEN(RowValue)-1)
         WHEN CHARINDEX('S',RowValue)>0 AND CHARINDEX('L',RowValue)>0 THEN RIGHT(RowValue,LEN(RowValue)-CHARINDEX('L',RowValue))
         ELSE NULL
END AS L
    ,RowValue
    FROM @YourTable
KM.
我刚刚看到问题的最后一行f no "S" or "L" is found, the default value is zero.要实现这一点,只需将两个CASE语句的ELSE子句从ELSE NULL改为ELSE 0。另外,问题中的样本数据没有包含NULL行或像'ABC'这样的垃圾值的行,我的查询将返回CASE的默认值。
很好,你的第二个建议 "开箱即用"。谢谢!:)
ktharsis
ktharsis
发布于 2010-02-24
0 人赞同
SELECT 
SVal = CASE
WHEN PATINDEX('S%L%', TextVal) > 0 THEN REPLACE(LEFT(TextVal, CHARINDEX('L', TextVal) - 1), 'S', '')
  WHEN PATINDEX('S%', TextVal) > 0 THEN REPLACE(TextVal, 'S', '')
  ELSE '0'
END,
LVal = CASE
WHEN PATINDEX('S%L%', TextVal) > 0 THEN REPLACE(RIGHT(TextVal, LEN(TextVal) - CHARINDEX('L', TextVal)), 'L', '')
  WHEN PATINDEX('L%', TextVal) > 0 THEN REPLACE(TextVal, 'L', '')
  ELSE '0'
FROM StringList 

假设S总是在L之前。另外,你可能想把结果铸成数字(现在是字符串),这取决于你对输出的需求。

Ray
Ray
发布于 2010-02-24
0 人赞同

我建议使用一个基于clr的函数,该函数将使用一个regex来从字符串中提取S或L值。你可以像这样使用它。

insert new_table (s_value, l_value)
  select getValue('S', original_value), getValue('L', original_value)
    from original_table
mjallday
mjallday
发布于 2010-02-24
0 人赞同

未经测试,但假设s总是出现在l之前,应该是接近的。

select
case when charindex(data, 's') <> 0 then
        substr(data, charindex(data, 's'), charindex(data ,'l'))
    else 0 end