我有一个示例数据
DECLARE @Table1 table ([name] varchar(62));
INSERT INTO @Table1
([name])
VALUES
('2018-08-08 23:02:57,731 INFO [AllRequestInterceptor] CRTST020'),
('2018-08-08 23:03:11,687 INFO [SOAPLoggingHandler] CRTST020'),
('2018-08-08 23:03:02,028 ERROR [AJAXController] CRTST003');
我正在尝试根据提供的空格创建4列。
SELECT
Reverse(ParseName(Replace(Reverse([name]), ' ', '.'), 1)) As [M1]
,Reverse(ParseName(Replace(Reverse([name]), ' ', '.'), 2)) As [M2]
,Reverse(ParseName(Replace(Reverse([name]), ' ', '.'), 3)) As [M3]
,Reverse(ParseName(Replace(Reverse([name]), ' ', '.'), 4)) As [M4]
FROM (Select [name] from @Table1
) As [x]
预期输出:
Date Name Req Code
8/8/2018 23:02:57,731 INFO [AllRequestInterceptor] CRTST020
8/8/2018 23:03:11,687 INFO [SOAPLoggingHandler] CRTST020
8/8/2018 23:03:02,028 ERROR [AJAXController] CRTST003
答案 0 :(得分:2)
这不是理想的选择,但是假设,唯一的空格将出现在date
值中(而不是作为分隔符),您可以使用字符串分隔符和然后将数据旋转回去。使用delimitedsplit8k_LEAD
,因为顺序位置很重要:
WITH CTE AS(
SELECT T1.name,
DS.ItemNumber,
DS.Item,
ROW_NUMBER() OVER (PARTITION BY T1.[name] ORDER BY DS.ItemNumber ASC) AS RN
FROM @Table1 T1
CROSS APPLY dbo.delimitedsplit8k_LEAD(T1.[name],' ') DS
WHERE DS.Item <> '')
SELECT MAX(CASE WHEN RN = 1 THEN Item END) + ' ' + MAX(CASE WHEN RN = 2 THEN Item END) AS [Date],
MAX(CASE WHEN RN = 3 THEN Item END) AS [Name],
MAX(CASE WHEN RN = 4 THEN Item END) AS Req,
MAX(CASE WHEN RN = 5 THEN Item END) AS Code
FROM CTE
GROUP BY [Name];
大声,如果您不能创建功能,则可以做错事(但很糟糕):
DECLARE @Table1 table ([name] varchar(62));
INSERT INTO @Table1 ([name])
VALUES ('2018-08-08 23:02:57,731 INFO [AllRequestInterceptor] CRTST020'),
('2018-08-08 23:03:11,687 INFO [SOAPLoggingHandler] CRTST020'),
('2018-08-08 23:03:02,028 ERROR [AJAXController] CRTST003');
DECLARE @Delimiter char(1) = ' ';
WITH E1 (N) AS
(SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 1
UNION ALL
SELECT 1), --10E+1 or 10 rows
E2 (N) AS
(SELECT 1
FROM E1 AS a,
E1 AS b), --10E+2 or 100 rows
E4 (N) AS
(SELECT 1
FROM E2 AS a,
E2 AS b), --10E+4 or 10,000 rows max
cteTally (N) AS
( --==== This provides the "zero base" and limits the number of rows right up front
-- for both a performance gain and prevention of accidental "overruns"
SELECT 0
UNION ALL
SELECT TOP 62
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM E4),
cteStart (N1, [name]) AS
( --==== This returns N+1 (starting position of each "element" just once for each delimiter)
SELECT t.N + 1,
T1.[name]
FROM cteTally AS t
CROSS JOIN @Table1 AS T1
WHERE (SUBSTRING(T1.[name], t.N, 1) = @Delimiter
OR t.N = 0)),
Splits AS
(SELECT s.[name],
ROW_NUMBER() OVER (ORDER BY s.N1) AS ItemNumber,
SUBSTRING(s.[name], s.N1, ISNULL(NULLIF((LEAD(s.N1, 1, 1) OVER (PARTITION BY s.[name] ORDER BY s.N1) - 1), 0) - s.N1, 8000)) AS item
FROM cteStart AS s),
CTE AS
(SELECT name,
ItemNumber,
item,
ROW_NUMBER() OVER (PARTITION BY [name] ORDER BY ItemNumber ASC) AS RN
FROM Splits
WHERE item <> '')
SELECT MAX(CASE WHEN RN = 1 THEN item END) + ' ' + MAX(CASE WHEN RN = 2 THEN item END) AS [Date],
MAX(CASE WHEN RN = 3 THEN item END) AS [Name],
MAX(CASE WHEN RN = 4 THEN item END) AS Req,
MAX(CASE WHEN RN = 5 THEN item END) AS Code
FROM CTE
GROUP BY [name];
答案 1 :(得分:2)
尝试一下
Date Name Req Code
----------------------------------------------------------------
2018-08-08 23:02:57,731 INFO [AllRequestInterceptor] CRTST020
2018-08-08 23:03:02,028 ERROR [AJAXController] CRTST003
2018-08-08 23:03:11,687 INFO [SOAPLoggingHandler] CRTST020
结果
document
答案 2 :(得分:1)
您的数据几乎是固定长度的格式。对于示例数据,可以使用字符串函数:
select left(name, 23) as date,
trim(substring(name, 25, 6)) as name,
trim(substring(name, 31, len(name) - 39)) as req,
right(name, 8) as code
from @table1 t1;
Here是db <>小提琴。
答案 3 :(得分:1)
您可以为此使用多个apply
:
select substring(name, 0, n) as [Date], substring(d, 0, d1) as Name, substring(d, d1, d2-d1+1) as Req, substring(d, d2+1, len(name)) as Code
from @Table1 t1 cross apply
( values (patindex('%[a-z]%', name))
) tt(n) cross apply
( values (substring(name, n, len(name)))
) ttt(d) cross apply
( values (charindex('[', d), charindex(']', d))
) tttt(d1, d2);