如何在SQL查询中第3次出现字符之前抓取所有内容

时间:2017-07-25 19:43:06

标签: sql sql-server

如何在第3天之前获取所有数据?'? 下面我有样本数据:

000700-      - - 8  
015111-      - 005 -  
019999-      - 005 -  
A01- 01200-   0 - 5  
A01-012000- - 5  
A02-015450- - 5  
A02-015450- 003 - 1  
D08-020700- - 8  
D08-020710- - 5  
D08-020710- 013 - 1  
D08-020710- 013 - 3  

这就是我所做的,我得到了正确的信息。但由于删除了一些空格,我无法进行适当的比较以获取Crystal Reports中的数据。

reverse(substring(reverse(a.ProjectionCode),
        charindex('-', re‌​verse(a.ProjectionCo‌​de)) + 1, 
        len(reverse(a.ProjectionCode))))) as PhaseCode

5 个答案:

答案 0 :(得分:1)

试试这个:

declare @str varchar(200) = 'A02-015450- 003 - 1';

select SUBSTRING(@str, 1, LEN(@str) - CHARINDEX('-',  REVERSE(@str), 1));

答案 1 :(得分:0)

您对此输出的期望并不完全清楚。但是猜猜你可以在这里使用PARSENAME,因为你的数据总是正好是三个破折号。请注意,如果您的数据中有任何句点,则无法正常运行。在完美的世界中,这些数据不会像这样在单个列中分隔。它应该分布在列中。你在这里违反了1NF。

declare @Something table
(
    SomeValue varchar(50)
)

insert @Something
values
('000700- - - 8')
,('015111- - 005 -')
,('019999- - 005 -')
,('A01- 01200- 0 - 5')
,('A01-012000- - 5')
,('A02-015450- - 5')
,('A02-015450- 003 - 1')
,('D08-020700- - 8')
,('D08-020710- - 5')
,('D08-020710- 013 - 1')
,('D08-020710- 013 - 3 ')

select *
    , parsename(replace(SomeValue, '-', '.'), 2)
from @Something

答案 2 :(得分:0)

这应该可以满足您的需求,即使在给定行中有多于或少于3个破折号的情况下也能正常工作。

-- Test Data...
INSERT #TestData (SomeString) VALUES 
    ('000700- - - 8'),
    ('015111- - 005 -'),
    ('019999- - 005 -'),
    ('A01- 01200- 0 - 5'),
    ('A01-012000- - 5'),
    ('A02-015450- - 5'),
    ('A02-015450- 003 - 1'),
    ('D08-020700- - 8'),
    ('D08-020710- - 5'),
    ('D08-020710- 013 - 1'),
    ('D08-020710- 013 - 3'),
    ('1-2-3-4-5-6-7-8-9'),  -- More than 3 dashes
    ('zaq12wsx-vfr445tgb'), -- lesst than 3 dashes
    ('987654321345678');    -- No dashes

-- Query...
SELECT 
    td.SomeString,
    LEFT(td.SomeString, ISNULL(d3.Dash, LEN(td.SomeString) + 1)- 1)
FROM 
    #TestData td
    CROSS APPLY ( VALUES (NULLIF(CHARINDEX('-', td.SomeString, 1), 0)) ) d1 (Dash)
    CROSS APPLY ( VALUES (NULLIF(CHARINDEX('-', td.SomeString, d1.Dash + 1), 0)) ) d2 (Dash)
    CROSS APPLY ( VALUES (NULLIF(CHARINDEX('-', td.SomeString, d2.Dash + 1), 0)) ) d3 (Dash);

编辑:添加功能和使用代码......

iTVF

CREATE FUNCTION dbo.tfn_TextLeftOfThirdDash
/* =============================================================================================
iTVF that returns all text to the left og the 3rd dash in a string of text
============================================================================================= */
(
    @String VARCHAR(8000)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
    SELECT 
        StringRemain = LEFT(@String, ISNULL(d3.Dash, LEN(@String) + 1)- 1)
    FROM 
        ( VALUES (NULLIF(CHARINDEX('-', @String, 1), 0)) ) d1 (Dash)
        CROSS APPLY ( VALUES (NULLIF(CHARINDEX('-', @String, d1.Dash + 1), 0)) ) d2 (Dash)
        CROSS APPLY ( VALUES (NULLIF(CHARINDEX('-', @String, d2.Dash + 1), 0)) ) d3 (Dash);
GO 

如何使用该功能...

SELECT 
    td.SomeString, 
    l3d.StringRemain
FROM
    #TestData td
    CROSS APPLY dbo.tfn_TextLeftOfThirdDash(td.SomeString) l3d;

HTH, 杰森

答案 3 :(得分:0)

用于搜索字符串的tsql函数charindex接受从哪里开始的参数。可以使用另一个对charindex的调用来计算此起始位置。

SELECT 
  SUBSTRING(col, 1,
    CHARINDEX('-', col,
      CHARINDEX('-', col,
        CHARINDEX('-', col)+1
      )+1
    )-1
  )
FROM table

答案 4 :(得分:0)

SQL Server本身没有任何内容可以确定字符或字符串的第n个位置。我的方法是创建自己的方法。像这样:

CREATE FUNCTION [dbo].[nthOccurencePos](@input VARCHAR(128), @delimiter CHAR(1), @nth INT)
RETURNS INT
BEGIN
    DECLARE @result INT;
    WITH cteExample AS
    (
        --Find the index of the first delimiter
        SELECT 1 AS rowCounter, CHARINDEX(@delimiter, @input, 1) delPos
        UNION ALL
        --Move over one character and find the index of the next delimiter
        SELECT rowCounter + 1, CHARINDEX(@delimiter, @input, delPos + 1) 
        FROM cteExample
        WHERE delPos > 0 --When you come up empty, stop
    )
    SELECT @result = delPos FROM cteExample WHERE rowCounter = @nth;
    RETURN @result;
END

现在使用此函数来获取第3个连字符之前的所有内容,如下所示:

DECLARE @tbl TABLE(sample VARCHAR(128))

INSERT @tbl VALUES
('000700- - - 8')
,('015111- - 005 -')
,('019999- - 005 -')
,('A01- 01200- 0 - 5')
,('A01-012000- - 5')
,('A02-015450- - 5')
,('A02-015450- 003 - 1')
,('D08-020700- - 8')
,('D08-020710- - 5')
,('D08-020710- 013 - 1')
,('D08-020710- 013 - 3 ');


SELECT LEFT(sample, dbo.nthOccurencePos(sample, '-', 3) - 1) BeforeHyphen3
FROM @tbl;

虽然在您的情况下不使用它,但更常见的是需要在分隔字符串中的第n列数据。例如:

DECLARE @delim NVARCHAR(128);
SET @delim = 'abcdefg-hijklmnop-qrstuv-wxyz';
SELECT SUBSTRING(@delim, dbo.nthOccurencePos(@delim, '-', 2) + 1, dbo.nthOccurencePos(@delim, '-', 3) - dbo.nthOccurencePos(@delim, '-', 2) - 1) as thirdColumn