我使用的是SQL Server 2008 R2,我将数据格式AA-BB-CCCCCCCC-DDDDDDDD-EEEE
存储在一列中。我需要用T-SQL内联将它分成5个单独的列(我不想为此目的创建一个函数,但是如果有严重的性能提升我会调查它,这里有权限问题我必须处理)。我正在创建一个视图来模仿另一台服务器上类似表的布局。
所以,我希望我的输出看起来像这样:
+------+------+----------+----------+------+
| Col1 | Col2 | Col3 | Col4 | Col5 |
+------+------+----------+----------+------+
| AA | BB | CCCCCCCC | DDDDDDDD | EEEE |
+------+------+----------+----------+------+
现在,我有一些有用的东西,但对我来说似乎完全没效率,在我的测试中对此视图执行查询非常耗时。我使用CTE和XML来打破列,但这需要诸如转义&符号之类的东西等。
所以,我现在拥有的是:
WITH cte (ColA, ColB, Colc, etc.)
AS
(
SELECT
CONVERT(XML,'<Account><Attribute>'
+ REPLACE(REPLACE(MY_COLUMN,'&','&'),'-', '</Attribute><Attribute>')
+ '</Attribute></Account>') as ACCOUNT_VALUE
)
SELECT
ACCOUNT_VALUE.value('/Account[1]/Attribute[1]','varchar(2)') as Col1,
ACCOUNT_VALUE.value('/Account[1]/Attribute[2]','varchar(2)') as Col2,
ACCOUNT_VALUE.value('/Account[1]/Attribute[3]','varchar(8)') as Col3,
ACCOUNT_VALUE.value('/Account[1]/Attribute[4]','varchar(8)') as Col4,
ACCOUNT_VALUE.value('/Account[1]/Attribute[5]','varchar(4)') as Col5
FROM cte
这样可以很好地返回数据,但需要特别长的时间。那么,是否有更好的方法将带连字符的数据分成T-SQL语句中的列(最好没有函数等)?该表有数百万行需要分成不同的列。
我昨天通过几个小时的谷歌搜索得到了这一点,并没有真正找到我能够工作的另一种选择。
答案 0 :(得分:1)
试试这个:
CREATE TABLE Test
(
LongText VARCHAR(400)
)
INSERT INTO Test (LongText)
VALUES('AA-BB-CCCCCCCC-DDDDDDDD-EEEE'),
('BB-CC-DDDDDDDD-EEEEEEEE-FFFF')
;WITH CTE AS
(
--initial part
SELECT LongText, 1 AS ColNo, LEFT(LongText, CHARINDEX('-', LongText)-1) AS Part,
RIGHT(LongText, LEN(LongText) - CHARINDEX('-', LongText)) AS Remainder
FROM Test
WHERE CHARINDEX('-', LongText)>0
--recursive part, gets 'Part' till the last '-'
UNION ALL
SELECT LongText, ColNo + 1 AS ColNo,LEFT(Remainder, CHARINDEX('-', Remainder)-1) AS Part,
RIGHT(Remainder, LEN(Remainder) - CHARINDEX('-', Remainder)) AS Remainder
FROM CTE
WHERE CHARINDEX('-', Remainder)>0
--recursive part, gets the last 'Part' (there is no '-')
UNION ALL
SELECT LongText, ColNo + 1 AS ColNo,Remainder AS Part,NULL AS Remainder
FROM CTE
WHERE CHARINDEX('-', Remainder)=0
)
SELECT [1],[2],[3],[4],[5]
FROM (
SELECT LongText, ColNo, Part
FROM CTE
) AS DT
PIVOT(MAX(Part) FOR ColNo IN ([1],[2],[3],[4],[5])) AS PT
答案 1 :(得分:0)
如果您知道您的数据有设定的长度,您可以使用以下内容:
Declare @value as Varchar(50);
Set @value = 'AA-BB-CCCCCCCC-DDDDDDDD-EEEE'
Select left(@value, 2) as col1, SUBSTRING(@value, 4, 2) as col2,
SUBSTRING (@value, 7, 8) as col3
等。另外,你可以使用类似的模式,使用charindex()对&#39; - &#39;用于定义子字符串的起点和终点的字符。 Maciej的方法与此类似。
答案 2 :(得分:0)
如果你总是有5个部分,这种方法可能比XML处理更快:
select
left(MY_COLUMN, P1.P1-1) as PART1,
substring(MY_COLUMN, P1.P1+1,P2.P2-P1.P1-1) as PART2,
substring(MY_COLUMN, P2.P2+1,P3.P3-P2.P2-1) as PART3,
substring(MY_COLUMN, P3.P3+1,P4.P4-P3.P3-1) as PART4,
substring(MY_COLUMN, P4.P4+1,8000) as PART5
from
MY_TABLE
cross apply (select charindex('-', MY_COLUMN) as P1) P1
cross apply (select charindex('-', MY_COLUMN, P1.P1+1) as P2) P2
cross apply (select charindex('-', MY_COLUMN, P2.P2+1) as P3) P3
cross apply (select charindex('-', MY_COLUMN, P3.P3+1) as P4) P4
cross apply (select charindex('-', MY_COLUMN, P4.P4+1) as P5) P5