Я хотел извлечь все детали до второй / (косая черта) из моей таблицы в SQL Server. Есть идеи?

website
AA.AA/AB/123
www.google.com/en/abcd/
yahoo.com/us/dev
gmail.com

ouput
website
AA.AA/AB
www.google.com/en
yahoo.com/us
gmail.com
0
rob_irkland 15 Янв 2021 в 21:24

4 ответа

Лучший ответ

Возможно, это подойдет вам:

DECLARE @Table TABLE (Col1 NVARCHAR(100))
INSERT @Table VALUES
('website'),
('AA.AA/AB/123'),
('www.google.com/en/abcd/'),
('yahoo.com/us/dev'),
('gmail.com')



SELECT 
COALESCE(
    NULLIF(
        SUBSTRING(Col1,1,CHARINDEX('/',Col1,CHARINDEX('/',Col1)+1))
        ,'')
   ,Col1    
    ) AS Col1
FROM @Table
1
BJones 15 Янв 2021 в 18:31

Если вы используете SQL Server 2017 или 2019, вы можете использовать STRING_AGG() для повторной сборки вывода из STRING_SPLIT():

SELECT STRING_AGG(x.value, '/')
FROM dbo.table_name CROSS APPLY 
(
  SELECT value, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
  FROM STRING_SPLIT(Col1, '/') AS ss
) AS x(value, rn)
WHERE x.rn <= 2
GROUP BY Col1;

Вы могли бы сказать:

"Но, Аарон, вывод STRING_SPLIT() не гарантируется, что он в порядке; на самом деле об этом предупреждает документация."

Это правда; в документации это сказано. Но у меня есть официальное сообщение от Microsoft, что, по крайней мере, в текущих версиях, вывод может быть только в порядке слева направо. У меня скоро появится сообщение об этом в блоге, и я вернусь и обновлю подобные ответы, где я известно, что они немного поиграли в Chicken Little.

Если вы используете более старую версию или не доверяете ей, вы можете использовать возвращающую табличное значение функцию, которая сохраняет порядок входной строки, например из этого ответа:

CREATE FUNCTION [dbo].[SplitString]
(
    @List NVARCHAR(MAX),
    @Delim VARCHAR(255)
)
RETURNS TABLE
AS
    RETURN ( SELECT [Value], idx = RANK() OVER (ORDER BY n) FROM 
      ( 
        SELECT n = Number, 
          [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
          CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
        FROM (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
          FROM sys.all_objects) AS x
          WHERE Number <= LEN(@List)
          AND SUBSTRING(@Delim + @List, [Number], LEN(@Delim)) = @Delim
      ) AS y
    );

Имея эту функцию, вы можете делать следующее и теперь чувствовать себя безопаснее, полагаясь на порядок (за счет более дорогостоящего запроса):

;WITH src AS 
(
  SELECT Col1, idx, Value  
  FROM dbo.table_name CROSS APPLY dbo.SplitString(Col1, '/')
)
SELECT STUFF((SELECT '/' + Value
  FROM src
  WHERE src.idx <= 2 AND Col1 = t.Col1
  ORDER BY idx
  FOR XML PATH, TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, '')   
FROM dbo.table_name AS t
GROUP BY Col1;
1
Aaron Bertrand 15 Янв 2021 в 20:04

Я нахожу cross apply удобным в таких ситуациях

select case when str like '%/%' then left(str, i2-1) else str end as str
from t
cross apply (select charindex( '/', str ) as i1) t2           --position of first slash
cross apply (select charindex( '/', str, (i1 + 1)) as i2 ) t3 --position of second slash
0
Phil Coulson 15 Янв 2021 в 19:26

Ниже приведен простой запрос, который вы можете попробовать. В приведенном ниже запросе замените " colName " на свое имя столбца и Table_1 на свое имя таблицы .

SELECT  LEFT([colName], charindex('/', [colName], charindex('/', [colName])+1)-1) AS [AfterSecondPipe]
FROM    [Table_1]
0
RAM G 15 Янв 2021 в 19:39
65741625