STUFF FUNCTION

  • Hi Guys,

    I have a column in a table that I have stored in the format;

    --/---/--/--

    e.g 01/345/76/98

    But I need to change it to the format;

    --/---/---/--

    e.g 01/345/076/98, this is to say, I need to replace the second '/' at position 7 with '/0'.

    This will increase the length of the column to 13, and I have allowed for this.

    I have tested with stuff as below;

    SELECT STUFF(IndUniqId, 7, 1, '/0')from form5Test

    the name of the column is IndUniqId

    this works pretty fine as I want except it doesn't write the values, but only selects them and when I go back to the table, I find them as Original.

    Does anyone have an idea how to go around this?

    Many thanks

  • You will have to run an UPDATE query like below

    UPDATEform5Test

    SETIndUniqId = STUFF(IndUniqId, 7, 1, '/0')


    Kingston Dhasian

    How to post data/code on a forum to get the best help - Jeff Moden
    http://www.sqlservercentral.com/articles/Best+Practices/61537/

  • Thanks Kingstone

  • mugahjoseph (4/23/2010)


    Hi Guys,

    I have a column in a table that I have stored in the format;

    --/---/--/--

    e.g 01/345/76/98

    But I need to change it to the format;

    --/---/---/--

    e.g 01/345/076/98, this is to say, I need to replace the second '/' at position 7 with '/0'.

    This will increase the length of the column to 13, and I have allowed for this.

    I have tested with stuff as below;

    SELECT STUFF(IndUniqId, 7, 1, '/0')from form5Test

    the name of the column is IndUniqId

    this works pretty fine as I want except it doesn't write the values, but only selects them and when I go back to the table, I find them as Original.

    Does anyone have an idea how to go around this?

    Many thanks

    As a side bar, I wouldn't store data in a denormalized form like that. Instead, I'd store the data in 4 separate columns so that indexes actually mean something and you don't have to parse or use SUBSTRING to execute simple inqueries.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Kingston,

    Would you be able to help me with the following code utilizing SQL SERVER STUFF function.

    I need to acquire the total number of beds in a vertically placement like the following:

    0776,Hospital,201106072001,12,26,0,0,9,0,1,0,0,0

    I used the following code to create the above test data:

    stuff (( select ',' +

    cast(sum(case

    when placement in ('1','2','5','7') then 1

    else 0

    end) as varchar)

    FROM @CENSUS_WORK

    group by (placement)

    for XML PATH('')

    ),1,0,'')

    However the state does not want the 0 instead they would like me to put a ',' where our site currently does not have a certain

    bed category which is displayed above with a 0.

    I attempted to update the code above to:

    stuff (( select ',' +

    cast(sum(case

    when placement = '1' then 1

    when placement = '2' then 1

    when placement = '3' then ','+convert(varchar(1),placement)

    when placement = '5' then 1

    when placement = '6' then ','+convert(varchar(1),placement)

    when placement = '7' then 1

    when placement = '8' then ','+convert(varchar(1),placement)

    when placement = '9' then ','+convert(varchar(1),placement)

    when placement = '10' then ','+convert(varchar(1),placement)

    end) as varchar)

    FROM @CENSUS_WORK

    group by (placement)

    for XML PATH('')

    ),1,0,'')

    and receive the following ERROR:

    Msg 245, Level 16, State 1, Procedure usp_nh_HAvBed, Line 179

    Conversion failed when converting the varchar value ',3' to data type int.

    I am aware that the problem is occurring due to the different data type of data field [placement] int and (,) varchar, however I am not sure how to go about updating the 0 values to a ',' utilizing stuff function and the aggregate function of sum. Do I need to add another function

    to convert the int to varchar besides what I have above.

    Thank you

  • Hello,

    As I understand you want to replace ',0' by ',', right?.

    Try it,

    SELECT ',' + CASE

    WHEN TotalPlacement = 0 then ''

    WHEN Placement IN (1, 2, 5, 7) THEN CAST(TotalPlacement AS VARCHAR(9))

    ELSE ''

    END

    FROM (

    SELECT Placement, COUNT(*) AS TotalPlacement

    FROM @CENSUS_WORK

    group by Placement

    ) X

    for XML PATH('')

    I didn't try it but this instruction, or something like, could work.

    Regards,

    Francesc

  • Thank you For you reply, Code worked great except for the following problem:

    Code you provided produced the following results,

    ,18,22,,,12,,1,,,

    In which I was just missing one comma at the end. There is 10 bed categories and the "1" in the result set above represents bed category placement 7. The file specifications state that I should have 7,,,,

    Placement 7 = 7,

    Placement 8 = ,

    placement 9 = ,

    placement 10 = ,

    Any Idea what I am missing from the code below.

    Also,

    I had to update the code to test for a specific placement values due to the fact if Placement 1

    contains a 0 I need to display the zero value. I only want the comma for specific placement values.

    The updated code is below.

    SELECT

    ',' + CASE

    WHEN placement IN (1, 2, 5, 7) THEN CAST(TotalPlacement AS VARCHAR(9))

    WHEN placement IN (3, 4, 6, 8, 9, 10) and TotalPlacement = 0 then ','

    END

    FROM (

    SELECT placement, COUNT(*) AS TotalPlacement

    FROM Raw_Data$

    group by placement

    ) X

    for XML PATH('')

  • Hello,

    well, that's I understand from your post:

    - For placements 1, 2, 5, 7 you want to show the count number (any value including zero),

    - for other placements you want to show the empty chain,

    - all those values are separated by comma.

    These conditions are coded in this SELECT clause,

    SELECT

    ',' + CASE

    WHEN placement IN (1, 2, 5, 7) THEN CAST(TotalPlacement AS VARCHAR(9))

    ELSE ''

    END

    About the commas I'm not sure about your specifications. If you want a comma at begin but no comma at end, that SELECT clause is Ok; if you want a comma at end but not at begin you should change " ',' + CASE..." by "CASE... + ',' ". And if you want both commas, so ten values delimited by eleven commas, maybe this dirty trick in the FROM clause will help you:

    FROM (

    SELECT placement, COUNT(*) AS TotalPlacement

    FROM Raw_Data$

    group by placement

    UNION SELECT 99, 0

    ) X

    Hope this helps,

    Francesc

  • Hello,

    First I would like to thank you for you assistance.

    You are correct on the following,

    - For placements 1, 2, 5, 7 I want to show the count number (any value including zero)

    - For other placements I want to show the empty chain ","

    I tested the following code in which everything looks good (including comma placement) the only problem is Placement "7" contains no data so i expect to see a 0 and it is not.

    results from code below:

    0776,Hospital,201106081032,10,16,,,8,,,,,

    Needs to be:

    0776,Hospital,201106081032,10,16,,,8,0,,,

    stuff ((

    SELECT ',' + CASE

    WHEN placement IN (1, 2, 5, 7) THEN CAST(TotalPlacement AS VARCHAR(9))

    ELSE ''

    END

    FROM (

    SELECT placement, COUNT(*) AS TotalPlacement

    FROM havbed$

    group by placement

    ) X

    for XML PATH('')

    ),1,0,'')

  • Hello again,

    executing this code,

    select stuff ((

    SELECT ',' + CASE

    WHEN placement IN (1, 2, 5, 7) THEN CAST(TotalPlacement AS VARCHAR(9))

    ELSE ''

    END

    FROM (

    SELECT 1 as placement, 10 AS TotalPlacement

    UNION SELECT 2, 16

    UNION SELECT 3, 1000

    UNION SELECT 4, 1000

    UNION SELECT 5, 8

    UNION SELECT 6, 1000

    UNION SELECT 7, 0

    UNION SELECT 8, 1000

    UNION SELECT 9, 1000

    UNION SELECT 10, 1000

    ) X

    for XML PATH('')

    ),1,1,'')

    (I changed a bit the last line to eliminate the initial coma) I obtain this result:

    10,16,,,8,,0,,,

    Maybe the problem is within this SELECT obtaining the totals,

    SELECT placement, COUNT(*) AS TotalPlacement

    FROM havbed$

    group by placement

    Could you verify if it returns any value for placement 7?. If there is no value for placement 7 (or 6, or 5, or...) there is nothing to concatenate. In this case you can still force a result for any missing value with another dirty trick, I tried it:

    SELECT OHNO.Placement, ISNULL(TotalPlacement, 0) AS TotalPlacement

    FROM (SELECT 1 AS Placement UNION SELECT 2 UNION SELECT 3 UNION SELECT 4

    UNION SELECT 5 UNION SELECT 6 UNION SELECT 7

    UNION SELECT 8 UNION SELECT 9 UNION SELECT 10) OHNO

    LEFT JOIN (

    SELECT 1 as placement, 10 AS TotalPlacement

    UNION SELECT 2, 16

    UNION SELECT 3, 1000

    --UNION SELECT 4, 1000

    --UNION SELECT 5, 8

    --UNION SELECT 6, 1000

    --UNION SELECT 7, 0

    UNION SELECT 8, 1000

    UNION SELECT 9, 1000

    UNION SELECT 10, 1000

    ) X

    ON OHNO.Placement = X.Placement

    Regards,

    Francesc

  • Hello,

    I am in agreement with you that the problem resides in the select statement. I am unsure on where to include the actual table Havbed with the code you provide me to confirm a 0 value for placement

    7. The code below is just returning a constant number I need the calculations based off the data in the

    table Havbed. Thank you again for your help. Do you think it would be better to create 10

    variables to hold the values for each placement and then utilize the stuff function to return the

    values vertically.

  • the problem resides in the select statement

    That's true?, nice, now the problem is located and you can fix it.

    I am unsure on where to include the actual table Havbed with the code you provide me

    The resultant query will be

    SELECT P.Placement, ISNULL(TotalPlacement, 0) AS TotalPlacement

    FROM Placements P

    LEFT JOIN (

    SELECT placement, COUNT(*) AS TotalPlacement

    FROM havbed$

    group by placement

    ) X

    ON P.Placement = X.Placement

    In this instruction the SELECT COUNT(*) will return the totals from your tables, the main SELECT will fill the holes.

    I'm supposing you have a 'Placements' table that contains these values from 1 to 10. If not you can substitute that 'Placements' table by (SELECT 1 AS Placement UNION SELECT 2 UNION ...SELECT 10)

    Do you think it would be better to create 10 variables to hold the values for each placement and then utilize the stuff function to return the values vertically.

    I'm not sure to understand your purpose, but now the solution looks simple enough.

    Well, now is time to finish working. If this code helps you I will finish the journey in satisfaction. Regards,

    Francesc

  • Thank you for all your help. Problem has been resolved.

Viewing 13 posts - 1 through 12 (of 12 total)

You must be logged in to reply to this topic. Login to reply