简体   繁体   English

SQL 在特定匹配的列中插入值

[英]SQL insert value into column on a specific match

I have a table consisting of roughly 4000 rows.我有一张由大约 4000 行组成的表格。 I am parsing through the column Text in the table and finding every instance of the word 'Fern' and from that the value in the third position of the string I am placing into another column named PONumber .我正在解析表中的Text列,并找到单词“Fern”的每个实例,并从中找到我放入另一列名为PONumber的字符串的第三个 position 中的值。 My third column RowKey is an identity column and tells me what rows the word I am searching for is on.我的第三列RowKey是一个标识列,它告诉我要搜索的单词在哪些行上。

For example the first instance of the word Fern is on row 1 while the next instance is on row 24. I am trying to get the value from the first instance into the PONumber column from row 1-23.例如,单词 Fern 的第一个实例位于第 1 行,而下一个实例位于第 24 行。我试图将第一个实例的值放入第 1-23 行的PONumber列中。 The next instance is on row 24 and ends on row 28, so I would need that value in the PONumber column on rows 24-28 and so on....下一个实例位于第 24 行并在第 28 行结束,因此我需要第 24-28 行的PONumber列中的该值,依此类推......

I am having trouble selecting only that range and placing the value into the corresponding rows in the PONumber column我无法仅选择该范围并将值放入PONumber列中的相应行

My code so far:到目前为止我的代码:

DECLARE @i INT, @maxCount INT;

select @maxCount = max(RowKey) from Flowers

WHILE @i <= @maxCount
SET @i = 1;
BEGIN
    SELECT Text, PONumber, RowKey FROM Flowers
    WHERE CHARINDEX('Fern', Text) > 0
    
    'I need to grab that value and INSERT INTO Number column

END

Sample Data:样本数据:

  Text                                      PONumber
1 Fern Flower 12345678  More text           12345678
.                                           12345678
.                                           12345678
.                                           12345678
.                                           12345678
.                                           12345678
.
23
24 Fern Flower 23456789 More text           PONumber
.                                           23456789
.                                           23456789
.                                           23456789
.                                           23456789
29  

    

Considering that all the values are prefixed with 'text' then is seems you could just use CHARINDEX and STUFF to remove that section of text:考虑到所有值都以'text'为前缀,那么您似乎可以只使用CHARINDEXSTUFF来删除该部分文本:

SELECT STUFF(YourColumn,1,NULLIF(CHARINDEX('text',YourColumn),0)+5,'') AS PONumber
FROM dbo.YourTable;

Edit: Based on the latest version, then it's not 'text' it's 'Fern Flower' and then you just need the left most characters to the next space (or end of the value?):编辑:根据最新版本,它不是'text'而是'Fern Flower' ,然后你只需要最左边的字符到下一个空格(或值的末尾?):

SELECT YT.YourColumn,
       LEFT(STUFF(YT.YourColumn,1,CI1.I-1,''),CI2.I - CI1.I) AS PONumber
FROM dbo.YourTable YT
     CROSS APPLY (VALUES(NULLIF(CHARINDEX('Fern Flower',YT.YourColumn),0)+LEN('Fern Flower') + 1))CI1(I)
     CROSS APPLY (VALUES(ISNULL(NULLIF(CHARINDEX(' ',YT.YourColumn,CI1.I),0),LEN(YT.YourColumn))))CI2(I);

db<>fiddle db<>小提琴

These types of situations are tricky and can be a real bear to wrestle with.这些类型的情况很棘手,可能是一个真正的熊。

My first note is to consider adding a PONumber column to your data and capturing that upon insert vs parsing text.我的第一个注意事项是考虑在您的数据中添加一个 PONumber 列,并在插入和解析文本时捕获它。 Having said that, here's an idea to address your current need.话虽如此,这里有一个解决您当前需求的想法。

First, here's a function designed to parse your "fern" po number from a text value:首先,这是一个 function 旨在从文本值解析您的“蕨类”po 编号:

CREATE FUNCTION dbo.GetPO (
    @text varchar(8000)
)
RETURNS varchar(255)
WITH RETURNS NULL ON NULL INPUT
AS
BEGIN

    DECLARE 
        @pos int = CHARINDEX ( 'fern', @text ),
        @po varchar(255);

    IF @pos > 0 BEGIN

        -- Locate the starting position of the first numeric value.
        -- Ass-u-mes *any* numeric value following the word "fern" is the expected po.

        WHILE ISNUMERIC ( SUBSTRING ( @text, @pos, 1 ) ) = 0 AND @pos <= LEN ( @text )
            SET @pos = @pos + 1;

        -- If @pos is not equal to @text's length then assume a @po value was found. 
        
        IF @pos < LEN ( @text ) BEGIN

            WHILE ISNUMERIC ( SUBSTRING ( @text, @pos, 1 ) ) = 1 BEGIN
                
                SET @po = ISNULL ( @po, '' ) + SUBSTRING ( @text, @pos, 1 );
                SET @pos = @pos + 1;

            END

        END

    END

    RETURN @po;

END
GO

Running SELECT dbo.GetPO ( 'Fern Flower 12345678 More text' );运行SELECT dbo.GetPO ( 'Fern Flower 12345678 More text' ); returns 12345678 .返回12345678

Next, to continue your previous PONumber in the event GetPO returned NULL , here is an example how you might go about that using dbo.GetPO :接下来,要在GetPO返回NULL的情况下继续您之前的 PONumber,这里是一个示例,您可以如何使用 dbo.GetPO 进行dbo.GetPO

DECLARE @Data table ( [Text] varchar(8000), RowKey int IDENTITY (1,1) );
INSERT INTO @Data VALUES
    ( 'Fern Flower 12345678  More text' ),
    ( '.' ),
    ( '.' ),
    ( 'Fern Flower 23456789 More text' ),
    ( '.' );

;WITH cte AS (
    
    SELECT
        RowKey,
        [Text],
        dbo.GetPO ( [Text] ) AS PONumber
    FROM @Data

)
SELECT
    RowKey,
    [Text],
    CASE
        WHEN PONumber IS NULL THEN (
            -- Get the most recent non-null PONumber.
            SELECT TOP 1 PONumber FROM cte AS x WHERE x.RowKey < cte.RowKey AND x.PONumber IS NOT NULL ORDER BY x.RowKey DESC
        )
        ELSE PONumber -- Keep the existing PONumber.
    END AS PONumber
FROM cte
ORDER BY RowKey;

Returns退货

+--------+---------------------------------+----------+
| RowKey |              Text               | PONumber |
+--------+---------------------------------+----------+
|      1 | Fern Flower 12345678  More text | 12345678 |
|      2 | .                               | 12345678 |
|      3 | .                               | 12345678 |
|      4 | Fern Flower 23456789 More text  | 23456789 |
|      5 | .                               | 23456789 |
+--------+---------------------------------+----------+

UPDATE更新

Here's an example of continuing your PONumber across NULL values using a combination of my and @Larnu's examples:这是使用我和@Larnu 的示例组合在 NULL 值中继续您的 PONumber 的示例:

;WITH cte AS (
    
    SELECT
        RowKey,
        [Text],
        LEFT( STUFF( YT.[Text], 1, CI1.I-1, '' ), CI2.I - CI1.I ) AS PONumber
    FROM @Data YT
    CROSS APPLY (
        VALUES ( NULLIF ( CHARINDEX ( 'Fern Flower', YT.[Text] ), 0 ) + LEN ( 'Fern Flower' ) + 1 )
    ) CI1 ( I )
    CROSS APPLY (
        VALUES ( ISNULL ( NULLIF ( CHARINDEX ( ' ', YT.[Text], CI1.I ), 0 ), LEN ( YT.[Text] ) ) )
    ) CI2 ( I )

)
SELECT
    RowKey,
    [Text],
    CASE
        WHEN PONumber IS NULL THEN (
            -- Get the most recent non-null PONumber.
            SELECT TOP 1 PONumber FROM cte AS x WHERE x.RowKey < cte.RowKey AND x.PONumber IS NOT NULL ORDER BY x.RowKey DESC
        )
        ELSE PONumber -- Keep the existing PONumber.
    END AS PONumber
FROM cte
ORDER BY RowKey;

Returns退货

+--------+---------------------------------+----------+
| RowKey |              Text               | PONumber |
+--------+---------------------------------+----------+
|      1 | Fern Flower 12345678  More text | 12345678 |
|      2 | .                               | 12345678 |
|      3 | .                               | 12345678 |
|      4 | Fern Flower 23456789 More text  | 23456789 |
|      5 | .                               | 23456789 |
+--------+---------------------------------+----------+

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM