help in logic

  • hi,

    i Have a table which contains a column called "value".

    The records are as below:

    Value

    -------

    1

    2

    3

    4

    5

    6

    7

    i need the output as single records as:

    1,2,3,4,5,6,7

    The logic is delimiting all the values by comma,

    In oracle , we implement this using wm_concat().

    Is there anyway to his in achieve this in sqlserver.

    Thanks

    Thanks,
    Pandeeswaran

  • pandeesh (12/29/2011)


    i Have a table which contains a column called "value".

    The records are as below:

    Value

    -------

    1

    2

    3

    4

    5

    6

    7

    i need the output as single records as:

    1,2,3,4,5,6,7

    The logic is delimiting all the values by comma,

    In oracle , we implement this using wm_concat().

    Is there anyway to his in achieve this in sqlserver.

    Yes. Search this forum for "row to column", zillions of posts 😉

    _____________________________________
    Pablo (Paul) Berzukov

    Author of Understanding Database Administration available at Amazon and other bookstores.

    Disclaimer: Advice is provided to the best of my knowledge but no implicit or explicit warranties are provided. Since the advisor explicitly encourages testing any and all suggestions on a test non-production environment advisor should not held liable or responsible for any actions taken based on the given advice.
  • Adding another thought. Is there any reason for doing it in database side? It should be done on Front End (application).

  • Dev (12/29/2011)


    Adding another thought. Is there any reason for doing it in database side? It should be done on Front End (application).

    Why? What's wrong with backend code formatting data as needed?

    _____________________________________
    Pablo (Paul) Berzukov

    Author of Understanding Database Administration available at Amazon and other bookstores.

    Disclaimer: Advice is provided to the best of my knowledge but no implicit or explicit warranties are provided. Since the advisor explicitly encourages testing any and all suggestions on a test non-production environment advisor should not held liable or responsible for any actions taken based on the given advice.
  • PaulB-TheOneAndOnly (12/29/2011)


    Dev (12/29/2011)


    Adding another thought. Is there any reason for doing it in database side? It should be done on Front End (application).

    Why? What's wrong with backend code formatting data as needed?

    It looks like presentation / display requirement and if Front End options are available then it should be done there only.

    I prefer to keep my database server away from unnecessary tasks.

  • Dev (12/29/2011)It looks like ...

    ...but you don't know, huh? why don't just answer what op asked for instead of going border line off topic for no good reason?

    Note: even if it has a question mark it is not really a question.

    _____________________________________
    Pablo (Paul) Berzukov

    Author of Understanding Database Administration available at Amazon and other bookstores.

    Disclaimer: Advice is provided to the best of my knowledge but no implicit or explicit warranties are provided. Since the advisor explicitly encourages testing any and all suggestions on a test non-production environment advisor should not held liable or responsible for any actions taken based on the given advice.
  • No. This is not a business requirement. and just i want to achieve this in sql server.

    i am looking in PIVOT to do this.

    Thanks

    Thanks,
    Pandeeswaran

  • i believe, it's not possible in PIVOT since i have only one field here.

    Thanks,
    Pandeeswaran

  • PaulB-TheOneAndOnly (12/29/2011)


    Dev (12/29/2011)It looks like ...

    ...but you don't know, huh? why don't just answer what op asked for instead of going border line off topic for no good reason?

    Note: even if it has a question mark it is not really a question.

    I didn’t expect such a reply. We are not here just to answer whatever been asked. Most of the times, OP come here with bad requirements or wrong assumptions in mind. For Example ‘Please help me in my Cursor’. It’s our responsibility to warn them.

    I am trying to understand your disagreement but not getting a single reason for it.

  • the below code works fine:

    SELECT STUFF( -- Remove first comma

    (

    SELECT ', ' + [ID] FROM -- create comma separated values

    (

    SELECT cast([ID] as VARCHAR) as [ID] FROM test --Your query here

    ) AS T FOR XML PATH('')

    )

    ,1,1,'')

    Where,

    "ID" is the column name in the table "test".

    Any other suggestions welcome...

    Thanks,
    Pandeeswaran

  • pandeesh (12/29/2011)


    Any other suggestions welcome...

    How about using coalesce?

    create table #test(id decimal);

    insert into #test values(1);

    insert into #test values(2);

    insert into #test values(3);

    insert into #test values(4);

    insert into #test values(5);

    insert into #test values(6);

    insert into #test values(7);

    declare @MyStuff varchar(256)

    select @MyStuff = coalesce(@MyStuff + ',', '') + cast(id as varchar)

    from #test;

    select @MyStuff

    _____________________________________
    Pablo (Paul) Berzukov

    Author of Understanding Database Administration available at Amazon and other bookstores.

    Disclaimer: Advice is provided to the best of my knowledge but no implicit or explicit warranties are provided. Since the advisor explicitly encourages testing any and all suggestions on a test non-production environment advisor should not held liable or responsible for any actions taken based on the given advice.
  • PaulB-TheOneAndOnly (12/29/2011)


    pandeesh (12/29/2011)


    Any other suggestions welcome...

    How about using coalesce?

    create table #test(id decimal);

    insert into #test values(1);

    insert into #test values(2);

    insert into #test values(3);

    insert into #test values(4);

    insert into #test values(5);

    insert into #test values(6);

    insert into #test values(7);

    declare @MyStuff varchar(256)

    select @MyStuff = coalesce(@MyStuff + ',', '') + cast(id as varchar)

    from #test;

    select @MyStuff

    I would prefer the FOR XML trick. Concatenating that way is not reliable.

    -- Gianluca Sartori

  • Gianluca Sartori (12/30/2011)


    PaulB-TheOneAndOnly (12/29/2011)


    pandeesh (12/29/2011)


    Any other suggestions welcome...

    How about using coalesce?

    create table #test(id decimal);

    insert into #test values(1);

    insert into #test values(2);

    insert into #test values(3);

    insert into #test values(4);

    insert into #test values(5);

    insert into #test values(6);

    insert into #test values(7);

    declare @MyStuff varchar(256)

    select @MyStuff = coalesce(@MyStuff + ',', '') + cast(id as varchar)

    from #test;

    select @MyStuff

    I would prefer the FOR XML trick. Concatenating that way is not reliable.

    oh ... I like FOR XML better myself but poster wanted an alternative.

    By the way, why is coalesce not reliable? don't tell me it gets tired and stops working after a while 😀

    _____________________________________
    Pablo (Paul) Berzukov

    Author of Understanding Database Administration available at Amazon and other bookstores.

    Disclaimer: Advice is provided to the best of my knowledge but no implicit or explicit warranties are provided. Since the advisor explicitly encourages testing any and all suggestions on a test non-production environment advisor should not held liable or responsible for any actions taken based on the given advice.
  • There's nothing wrong with COALESCE, it's the assignment in the SELECT list that makes the code unreliable.

    Here's a couple of articles on the subject:

    http://www.sqlmag.com/article/tsql3/row-concatenation-solutions-aren-t-all-equal

    http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

    -- Gianluca Sartori

  • Gianluca Sartori (1/2/2012)


    There's nothing wrong with COALESCE, it's the assignment in the SELECT list that makes the code unreliable.

    Here's a couple of articles on the subject:

    http://www.sqlmag.com/article/tsql3/row-concatenation-solutions-aren-t-all-equal

    http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/

    Whup! Be careful there, ol' friend. 🙂 I have to take exception to that "unreliable" part. "It Depends" on how you use it and how you sort it. Just because a query doesn't work doesn't mean it's unreliable... it just very reliably doesn't work the way you wrote it. 😀 In fact, the first article you cited clearly states, and I quote "He found that although [font="Arial Black"]these solutions produce the same result[/font], the time it takes to get those results varies significantly."

    I'll also prove that the second part (the part about time) of that is just because the author didn't optimize the "self-referencing variable".

    One of the myths about self-referencing variables used in concatenation is that they're slow. They are only slow if you don't know how they actually work and the things that can slow them down. To find that out, please see the following article (a bit out of date but the lessons still apply)...

    http://www.sqlservercentral.com/articles/Test+Data/61572/

    Now... would you believe that the method of using a self-referencing variable in a scalar UDF can actually beat the XML method? Probably not so I'll prove it. 😀

    Create the following. We have to use real tables instead of Temp Tables because we're going to create a Scalar Function that calls on the table...

    --===== Identify a nice, safe place to do this that everyone has because

    -- we need to conditionally drop a real table to test this.

    USE TempDB

    ;

    --===== Conditionally drop the test table to make reruns in SSMS easier

    IF OBJECT_ID('tempdb.dbo.TestData','U') IS NOT NULL

    DROP TABLE dbo.TestData

    ;

    --===== Create and populate test table.

    -- Column "RowNum" contains unique row numbers

    -- Column "SomeID" contains non-unique numbers

    -- (should be 1/400th of the row count to allow about 400 concatenated items per SomeInt).

    -- Column "SomeCode" has a range of "AA" to "ZZ" non-unique 2 character strings

    SELECT TOP 1000000 --<<<LOOK! CHANGE THIS NUMBER TO CHANGE THE NUMBER OF ROWS!

    RowNum = IDENTITY(INT,1,1),

    SomeID = ABS(CHECKSUM(NEWID()))%2500+1, --<<<LOOK! CHANGE THIS NUMBER TO 1/400th THE ROW COUNT

    SomeCode = CHAR(ABS(CHECKSUM(NEWID()))%26+65)

    + CHAR(ABS(CHECKSUM(NEWID()))%26+65)

    INTO dbo.TestData

    FROM sys.all_columns t1,

    sys.all_columns t2

    ;

    --===== Add what most folks would use as a PK/Clustered Index

    ALTER TABLE dbo.TestData

    ADD PRIMARY KEY CLUSTERED (RowNum)

    ;

    --===== Add an index to help XML and the function we're going to create

    CREATE INDEX IXC_TestData_Cover1 ON dbo.TestData(SomeID,SomeCode,RowNum)

    ;

    --===== Conditionally drop the function to make reruns in SSMS easier

    IF OBJECT_ID('tempdb.dbo.ConcatTest','FN') IS NOT NULL

    DROP FUNCTION dbo.ConcatTest

    ;

    GO

    --===== Create the function

    CREATE FUNCTION dbo.ConcatTest (@SomeID INT)

    RETURNS VARCHAR(8000) AS

    BEGIN

    DECLARE @Return VARCHAR(8000)

    SELECT @Return = ISNULL(@Return+',','')+SomeCode

    FROM dbo.TestData

    WHERE SomeID = @SomeID

    ORDER BY SomeCode

    RETURN @Return

    END

    ;

    GO

    I want you to notice that, despite what was said in the first article about a "small number of rows", the test data above contains a million rows with 2500 unique IDs and 400 "codes" to concatenate for each ID.

    Here's the test code...

    --===== Let the testing begin! First, conditionally drop the "target" tables

    IF OBJECT_ID('tempdb..#VariableMethod','U') IS NOT NULL

    DROP TABLE #VariableMethod

    ;

    IF OBJECT_ID('tempdb..#XmlMethod','U') IS NOT NULL

    DROP TABLE #XmlMethod

    ;

    PRINT '--===== Run the test on the function method ============================';

    SET STATISTICS TIME ON;

    SELECT SomeID, dbo.ConcatTest(SomeID) AS CSVString

    INTO #VariableMethod

    FROM dbo.TestData

    GROUP BY SomeID

    SET STATISTICS TIME OFF;

    PRINT '--===== Run the test on the XML method ============================';

    SET STATISTICS TIME ON;

    SELECT t1.SomeID,

    STUFF((SELECT ','+t2.SomeCode

    FROM dbo.TestData t2

    WHERE t1.SomeID = t2.SomeID FOR XML PATH('')),1,1,'') AS CsvString

    INTO #XmlMethod

    FROM dbo.TestData t1

    GROUP BY t1.SomeID;

    SET STATISTICS TIME OFF;

    Here's what I get for a return...

    --===== Run the test on the function method ============================

    SQL Server Execution Times:

    CPU time = 2937 ms, elapsed time = 3709 ms.

    (2500 row(s) affected)

    --===== Run the test on the XML method ============================

    SQL Server Execution Times:

    CPU time = 4219 ms, elapsed time = 4363 ms.

    (2500 row(s) affected)

    Of course, we have to prove that the two methods did the same thing...

    SELECT *

    FROM #VariableMethod vm

    FULL OUTER JOIN #XmlMethod xm

    ON vm.SomeID = xm.SomeID

    WHERE vm.CsvString <> xm.CsvString

    Anyway... to summarize this post, variable overlays (self referencing variables as some call them) for purposes of concatenation are not unreliable... they actually guaranteed to not work if you do an ORDER BY with a forumula in it and you can rely on that ;-). And, for VARCHAR(8000), they're certainly not slow if you do it right.

    Oh yeah... almost forgot. Since we created some real objects in Temp DB, here's the cleanup code to get rid fo them...

    --===== Housekeeping to clean up the permanent objects we created in TempDB.

    IF OBJECT_ID('tempdb.dbo.TestData','U') IS NOT NULL

    DROP TABLE dbo.TestData

    ;

    IF OBJECT_ID('tempdb.DROP FUNCTION dbo.ConcatTest','FN') IS NOT NULL

    DROP FUNCTION dbo.ConcatTest

    ;

    --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)

Viewing 15 posts - 1 through 15 (of 16 total)

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