2013-07-09 15 views
11

Jak podzielić poniższy ciąg na podstawie znaku "-"?SQL Server 2005 za pomocą CHARINDEX() Aby podzielić ciąg znaków

Więc gdybym miał ten ciąg: LD-23DSP-1430

Jak mogę podzielić ją na oddzielnych kolumnach tak:

LD  23DSP  1430 

także, czy istnieje sposób, aby podzielić każdy znak w osobnym polu gdybym potrzebne (bez "-")? Próbuję znaleźć sposób na zastąpienie każdej litery alfabetem NATO.

To będzie ... Lima Delta Dwadzieścia Trzy Delta Sierra Papa Czternaście Trzydzieści .... w jednym polu.

wiem, że mogę dostać po lewej stronie tak:

LEFT(@item, CHARINDEX('-', @item) - 1) 
+0

Można użyć 'funkcję substring' i zwiększyć wskaźnik start z charIndex pierwszego, drugiego, trzeciego trafienia i tak dalej. – jpw

+0

@jpw Jak znaleźć charindex drugiego dash? –

+0

@RaduGheorghiu Szukając myślnika w podłańcuchu zaczynającym się od charindexu pierwszego kreska + 1. – jpw

Odpowiedz

9

nie będę dokładnie powiedzieć, że jest łatwe i oczywiste, ale z zaledwie dwóch łączników, można odwrócić ciąg i nie jest zbyt dysk twardy:

with t as (select 'LD-23DSP-1430' as val) 
select t.*, 
     LEFT(val, charindex('-', val) - 1), 
    SUBSTRING(val, charindex('-', val)+1, len(val) - CHARINDEX('-', reverse(val)) - charindex('-', val)), 
     REVERSE(LEFT(reverse(val), charindex('-', reverse(val)) - 1)) 
from t; 

Poza tym możesz zamiast tego użyć split().

2

Spróbuj następujące zapytanie:

DECLARE @item VARCHAR(MAX) = 'LD-23DSP-1430' 

SELECT 
SUBSTRING(@item, 0, CHARINDEX('-', @item)) , 
SUBSTRING(
       SUBSTRING(@item, CHARINDEX('-', @item)+1,LEN(@ITEM)) , 
       0 , 
       CHARINDEX('-', SUBSTRING(@item, CHARINDEX('-', @item)+1,LEN(@ITEM))) 
      ), 
REVERSE(SUBSTRING(REVERSE(@ITEM), 0, CHARINDEX('-', REVERSE(@ITEM)))) 
+0

Dzięki za odpowiedź! Inne pytanie. Co jeśli przedmiot ma przeróżne kreski? Więc może to być LD-23DSP-MF-1430 Czy istnieje sposób policzenia liczby kresek i rozbicia każdej sekcji na pole? – user2531854

4

Oto mały funkcja, która zrobi „kodowanie NATO” dla Ciebie:

CREATE FUNCTION dbo.NATOEncode (
    @String varchar(max) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
RETURN (
    WITH L1 (N) AS (SELECT 1 UNION ALL SELECT 1), 
    L2 (N) AS (SELECT 1 FROM L1, L1 B), 
    L3 (N) AS (SELECT 1 FROM L2, L2 B), 
    L4 (N) AS (SELECT 1 FROM L3, L3 B), 
    L5 (N) AS (SELECT 1 FROM L4, L4 C), 
    L6 (N) AS (SELECT 1 FROM L5, L5 C), 
    Nums (Num) AS (SELECT Row_Number() OVER (ORDER BY (SELECT 1)) FROM L6) 
    SELECT 
     NATOString = Substring((
     SELECT 
      Convert(varchar(max), ' ' + D.Word) 
     FROM 
      Nums N 
      INNER JOIN (VALUES 
       ('A', 'Alpha'), 
       ('B', 'Beta'), 
       ('C', 'Charlie'), 
       ('D', 'Delta'), 
       ('E', 'Echo'), 
       ('F', 'Foxtrot'), 
       ('G', 'Golf'), 
       ('H', 'Hotel'), 
       ('I', 'India'), 
       ('J', 'Juliet'), 
       ('K', 'Kilo'), 
       ('L', 'Lima'), 
       ('M', 'Mike'), 
       ('N', 'November'), 
       ('O', 'Oscar'), 
       ('P', 'Papa'), 
       ('Q', 'Quebec'), 
       ('R', 'Romeo'), 
       ('S', 'Sierra'), 
       ('T', 'Tango'), 
       ('U', 'Uniform'), 
       ('V', 'Victor'), 
       ('W', 'Whiskey'), 
       ('X', 'X-Ray'), 
       ('Y', 'Yankee'), 
       ('Z', 'Zulu'), 
       ('0', 'Zero'), 
       ('1', 'One'), 
       ('2', 'Two'), 
       ('3', 'Three'), 
       ('4', 'Four'), 
       ('5', 'Five'), 
       ('6', 'Six'), 
       ('7', 'Seven'), 
       ('8', 'Eight'), 
       ('9', 'Niner') 
      ) D (Digit, Word) 
       ON Substring(@String, N.Num, 1) = D.Digit 
     WHERE 
      N.Num <= Len(@String) 
     FOR XML PATH(''), TYPE 
    ).value('.[1]', 'varchar(max)'), 2, 2147483647) 
); 

Funkcja ta będzie działać na nawet bardzo długie ciągi i wykonuje dość dobrze (uruchomiłem to na 100 000 znaków i powróciło w 589 ms). Oto przykład, w jaki sposób z niego korzystać:

SELECT NATOString FROM dbo.NATOEncode('LD-23DSP-1430'); 
-- Output: Lima Delta Two Three Delta Sierra Papa One Four Three Zero 

ja celowo mu funkcję wycenione tabela więc może być wstawiane do zapytania po uruchomieniu go przed wielu wierszy na raz, wystarczy użyć CROSS APPLY lub owinąć wyżej przykład w nawiasach, aby użyć go jako wartości w klauzuli SELECT (możesz umieścić nazwę kolumny w pozycji parametru funkcji).

+0

Fajna funkcja. Nie mogę go uruchomić na SQL 2005. Otrzymuję Msg 156, Level 15, State 1, Procedure NATOEncode, Line 21 Niepoprawna składnia w pobliżu słowa kluczowego "VALUES". – user2531854

+0

W SQL 2005 zmień to na 'INNER JOIN (SELECT 'A', 'Alpha' UNION ALL SELECT 'B', 'Beta' UNION ALL ...)'. – ErikE

+0

Dziewięć nie jest używane w alfabecie NATO, ponieważ można go pomylić z "nie" w języku niemieckim (Nein), który brzmi jak dziewięć. Prawidłowym odpowiednikiem liczby 9 w alfabecie NATO jest "niner". Twoje zdrowie! – levteck

0
USE [master] 
    GO 
    /****** this function returns Pakistan where as if you want to get ireland simply replace (SELECT SUBSTRING(@NEWSTRING,CHARINDEX('[email protected][email protected]$',@NEWSTRING)+5,LEN(@NEWSTRING))) with 
SELECT @NEWSTRING = (SELECT SUBSTRING(@NEWSTRING, 0,CHARINDEX('[email protected][email protected]$',@NEWSTRING)))******/ 
    SET ANSI_NULLS ON 
    GO 
    SET QUOTED_IDENTIFIER ON 
    GO 
    CREATE FUNCTION [dbo].[FN_RETURN_AFTER_SPLITER] 
    ( 
    @SPLITER varchar(max)) 
    RETURNS VARCHAR(max) 
    AS 
    BEGIN 

    --declare @testString varchar(100), 
    DECLARE @NEWSTRING VARCHAR(max) 
    -- set @teststring = '@ram?eez(ali)' 
    SET @NEWSTRING = @SPLITER ; 

    SELECT @NEWSTRING = (SELECT SUBSTRING(@NEWSTRING,CHARINDEX('[email protected][email protected]$',@NEWSTRING)+5,LEN(@NEWSTRING))) 
    return @NEWSTRING 
    END 
    --select [dbo].[FN_RETURN_AFTER_SPLITER] ('[email protected][email protected]$Pakistan') 
0
Create FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(200), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(10) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
     IF @end = 0 
      SET @end = LEN(@string) + 1 

     INSERT INTO @output (splitdata) 
     VALUES(SUBSTRING(@string, @start, @end - @start)) 
     SET @start = @end + 1 
     SET @end = CHARINDEX(@delimiter, @string, @start) 

    END 
    RETURN 

END**strong text** 
0
DECLARE @variable VARCHAR(100) = 'LD-23DSP-1430'; 
WITH Split 
     AS (SELECT @variable AS list , 
        charone = LEFT(@variable, 1) , 
        R = RIGHT(@variable, LEN(@variable) - 1) , 
        'A' AS MasterOne 
      UNION ALL 
      SELECT Split.list , 
        LEFT(Split.R, 1) , 
        R = RIGHT(split.R, LEN(Split.R) - 1) , 
        'B' AS MasterOne 
      FROM  Split 
      WHERE LEN(Split.R) > 0 
     ) 
SELECT * 
FROM Split 
OPTION (MAXRECURSION 10000); 
Powiązane problemy