Search code examples
sqlsql-serversubstringcharindex

sql query with substring charindex


table1
::::::::::::::::::::::::::::::::::
id | id_data | id_t | value 
1  | 43      | 1    | 
2  | 46      | 1    | 111,112,113
3  | 43      | 2    | 
4  | 46      | 2    | 90,5

table2
:::::::::::::::::::::::::::::::::::
id_value | cat
112      | cat1
5        | cat2

Hi, I need some help here if possible, please.

I need to update table1.value where id_data is 43 with table2.cat where id_value = the digits after value's ',' 'till the next ',' if there is any for each group in 'id_t'

I tried with a simple query but it's returning some null but 'value' can't be null

update table1 
set value = (select cat from table2 
            where convert(nvarchar,id_value) = substring(value,5,3))
where id_data='43'

I've been trying to incorporate CHARINDEX to take from the ',' but i just can't figure it out how it works.

Ideally it should look like this:

::::::::::::::::::::::::::::::::::
id | id_data | id_t | value 
1  | 43      | 1    | cat1
2  | 46      | 1    | 111,112,113
3  | 43      | 2    | cat2
4  | 46      | 2    | 90,5

Can anyone point me on the right direction, please?

I guess it's simple.. but I'm still learning...

thanks in advance.

::::::::::::::::

UPDATE1

WITH UpdateableCTE AS
(
    SELECT t1.id
          ,t1.id_data
          ,t1.id_t
          ,SecondNr
          ,(
            SELECT t2.cat
            FROM @table2 AS t2 WHERE t2.id_value=SecondNr
           ) AS NewCat
           ,t1.value
    FROM @table1 AS t1
    OUTER APPLY(SELECT CAST('<x>' + REPLACE(x.value,',','</x><x>') + '</x>' AS XML).value('/x[2]','int')
                FROM @table1 AS x 
                WHERE x.id_t=t1.id_t AND x.value IS NOT NULL AND id_data='46') AS ID(SecondNr)
    WHERE t1.value IS NULL
)
UPDATE UpdateableCTE SET value=NewCat;
--somehow where id_data='43'

I'll leave here one table that looks a little more to the real one with all the id_data and fields:

17974492    1   999251  somevalue
17974493    2   999251  somevalue
17974494    3   999251  somevalue
17974495    4   999251  somevalue
17974496    5   999251  somevalue
17974497    43  999251  (thishsouldbeupdated)
17974498    6   999251  somevalue
17974499    7   999251  somevalue
17974500    46  999251  111,311
17974501    8   999251  somevalue
17974502    9   999251  somevalue
17974503    10  999251  somevalue
17974504    11  999251  somevalue
17974505    12  999251  somevalue
17974506    13  999251  somevalue
17974507    1   999252  somevalue
17974508    2   999252  somevalue
17974509    3   999252  somevalue
17974510    4   999252  somevalue
17974511    5   999252  somevalue
17974512    43  999252  (thisshouldbeupdated)
17974513    6   999252  somevalue
17974514    7   999252  somevalue
17974515    46  999252  98,98
17974516    8   999252  somevalue
17974517    9   999252  somevalue
17974518    10  999252  somevalue
17974519    11  999252  somevalue
17974520    12  999252  somevalue
17974521    13  999252  somevalue

Solution

  • This is not clean, nor is it something I'd recommend, but you might find some help:

    DECLARE @table1 TABLE(id INT,id_data INT,id_t INT,value VARCHAR(100));
    INSERT INTO @table1 VALUES 
     (1,43,1,NULL)
    ,(2,46,1,'111,112,113')
    ,(3,43,2,NULL)
    ,(4,46,2,'90,5')
    
    DECLARE @table2 TABLE(id_value INT,cat VARCHAR(100));
    INSERT INTO @table2 VALUES
     (112,'cat1')
    ,(5,'cat2');
    
    SELECT t1.id
          ,t1.id_data
          ,t1.id_t
          ,ID.List
          ,(
            SELECT t2.cat
            FROM @table2 AS t2 WHERE CHARINDEX(',' + CAST(t2.id_value AS VARCHAR(100)) + ',',',' + ID.List + ',')>0
           )
    FROM @table1 AS t1
    OUTER APPLY(SELECT x.value FROM @table1 AS x WHERE x.id_t=t1.id_t AND x.value IS NOT NULL) AS ID(List)
    WHERE t1.value IS NULL
    

    UPDATE: Your explanation about use the second number as update

    Try this

    DECLARE @table1 TABLE(id INT,id_data INT,id_t INT,value VARCHAR(100));
    INSERT INTO @table1 VALUES 
     (1,43,1,NULL)
    ,(2,46,1,'111,112,113')
    ,(3,43,2,NULL)
    ,(4,46,2,'90,5')
    
    DECLARE @table2 TABLE(id_value INT,cat VARCHAR(100));
    INSERT INTO @table2 VALUES
     (112,'cat1')
    ,(5,'cat2');
    
    WITH UpdateableCTE AS
    (
        SELECT t1.id
              ,t1.id_data
              ,t1.id_t
              ,SecondNr
              ,(
                SELECT t2.cat
                FROM @table2 AS t2 WHERE t2.id_value=SecondNr
               ) AS NewCat
               ,t1.value
        FROM @table1 AS t1
        OUTER APPLY(SELECT CAST('<x>' + REPLACE(x.value,',','</x><x>') + '</x>' AS XML).value('/x[2]','int')
                    FROM @table1 AS x 
                    WHERE x.id_t=t1.id_t AND x.value IS NOT NULL) AS ID(SecondNr)
        WHERE t1.value IS NULL
    )
    UPDATE UpdateableCTE SET value=NewCat;
    
    SELECT * FROM @table1
    

    The concept is the updateable CTE, where you can use a normal SELECT to get the values you need. You then can update the derived table (as long as there are only columns of one single table affected) directly.

    The OUTER APPLY uses a trick with XML to split the CSV list in order to read the second number.

    UPDATE 2: Use your new sample data

    The following will use the new sample data and work with the IDs:

    DECLARE @table1 TABLE(id INT,id_data INT,id_t INT,value VARCHAR(100));
    INSERT INTO @table1 VALUES 
     (17974492,1,999251,'somevalue')
    ,(17974493,2,999251,'somevalue')
    ,(17974494,3,999251,'somevalue')
    ,(17974495,4,999251,'somevalue')
    ,(17974496,5,999251,'somevalue')
    ,(17974497,43,999251,'(thishsouldbeupdated)')
    ,(17974498,6,999251,'somevalue')
    ,(17974499,7,999251,'somevalue')
    ,(17974500,46,999251,'111,311')
    ,(17974501,8,999251,'somevalue')
    ,(17974502,9,999251,'somevalue')
    ,(17974503,10,999251,'somevalue')
    ,(17974504,11,999251,'somevalue')
    ,(17974505,12,999251,'somevalue')
    ,(17974506,13,999251,'somevalue')
    ,(17974507,1,999252,'somevalue')
    ,(17974508,2,999252,'somevalue')
    ,(17974509,3,999252,'somevalue')
    ,(17974510,4,999252,'somevalue')
    ,(17974511,5,999252,'somevalue')
    ,(17974512,43,999252,'(thisshouldbeupdated)')
    ,(17974513,6,999252,'somevalue')
    ,(17974514,7,999252,'somevalue')
    ,(17974515,46,999252,'98,98')
    ,(17974516,8,999252,'somevalue')
    ,(17974517,9,999252,'somevalue')
    ,(17974518,10,999252,'somevalue')
    ,(17974519,11,999252,'somevalue')
    ,(17974520,12,999252,'somevalue')
    ,(17974521,13,999252,'somevalue');
    
    DECLARE @table2 TABLE(id_value INT,cat VARCHAR(100));
    INSERT INTO @table2 VALUES
     (311,'cat1')
    ,(98,'cat2');
    
    WITH UpdateableCTE AS
    (
        SELECT t1.id
              ,t1.id_data
              ,t1.id_t
              ,SecondNr
              ,(
                SELECT t2.cat
                FROM @table2 AS t2 WHERE t2.id_value=SecondNr
               ) AS NewCat
               ,t1.value
        FROM @table1 AS t1
        OUTER APPLY(SELECT CAST('<x>' + REPLACE(x.value,',','</x><x>') + '</x>' AS XML).value('/x[2]','int')
                    FROM @table1 AS x 
                    WHERE x.id_t=t1.id_t AND x.id_data=46) AS ID(SecondNr)
        WHERE t1.id_data=43
    )
    UPDATE UpdateableCTE SET value=NewCat;
    
    SELECT * FROM @table1;