SQL Server 2000: Ideas for performing concatenation aggregation subquery

前端 未结 4 390
鱼传尺愫
鱼传尺愫 2020-12-19 07:31

i have a query that returns rows that i want, e.g.

QuestionID  QuestionTitle  UpVotes  DownVotes  
==========  =============  =======  =========  
2142075            


        
相关标签:
4条回答
  • 2020-12-19 07:40

    You can also take a look to this script. It's basically the cross join approach that Cade Roux also mentioned in his post.

    The above approach looks very clean: you have to do a view first and secondly create a statement based on the values in the view. The second sql statement you can build dynamically in your code, so it should be straight forward to use.

    0 讨论(0)
  • 2020-12-19 07:52

    I tried 3 approaches to this solution, the one posted here, activex scripting and UDF functions.

    The most effective script (speed-wise) for me was bizzarely Axtive-X script running multiple queries to get the additioanl data to concat.

    UDF took an average of 22 minutes to transform, the Subquery method (posted here) took around 5m and the activeX script took 4m30, much to my annoyance since this was the script I was hoping to ditch. I'll have to see if I can iron out a few more efficiencies elsewhere.

    I think the extra 30s is used by the tempdb being used to store the data since my script requires an order by.

    It should be noted that I am concatanating huge quantities of textual data.

    0 讨论(0)
  • 2020-12-19 07:59

    I'm not sure if this works in SQL Server 2000, but you can try it:

    --combine parent and child, children are CSV onto parent row
    CREATE TABLE #TableA (RowID int, Value1 varchar(5), Value2 varchar(5))
    INSERT INTO #TableA VALUES (1,'aaaaa','A')
    INSERT INTO #TableA VALUES (2,'bbbbb','B')
    INSERT INTO #TableA VALUES (3,'ccccc','C')
    
    CREATE TABLE #TableB (RowID int, TypeOf varchar(10))
    INSERT INTO #TableB VALUES (1,'wood')
    INSERT INTO #TableB VALUES (2,'wood')
    INSERT INTO #TableB VALUES (2,'steel')
    INSERT INTO #TableB VALUES (2,'rock')
    INSERT INTO #TableB VALUES (3,'plastic')
    INSERT INTO #TableB VALUES (3,'paper')
    
    
    SELECT
        a.*,dt.CombinedValue
        FROM #TableA        a
            LEFT OUTER JOIN (SELECT
                                 c1.RowID
                                     ,STUFF(
                                              (SELECT
                                                   ', ' + TypeOf
                                                   FROM (SELECT
                                                             a.RowID,a.Value1,a.Value2,b.TypeOf
                                                             FROM #TableA                 a
                                                                 LEFT OUTER JOIN #TableB  b ON a.RowID=b.RowID
                                                        ) c2
                                                   WHERE c2.rowid=c1.rowid
                                                   ORDER BY c1.RowID, TypeOf
                                                   FOR XML PATH('') 
                                              )
                                              ,1,2, ''
                                           ) AS CombinedValue
                                 FROM (SELECT
                                           a.RowID,a.Value1,a.Value2,b.TypeOf
                                           FROM #TableA                 a
                                               LEFT OUTER JOIN #TableB  b ON a.RowID=b.RowID
                                      ) c1
                                 GROUP BY RowID
                            ) dt ON a.RowID=dt.RowID
    

    OUTPUT from SQL Server 2005:

    RowID       Value1 Value2 CombinedValue
    ----------- ------ ------ ------------------
    1           aaaaa  A      wood
    2           bbbbb  B      rock, steel, wood
    3           ccccc  C      paper, plastic
    
    (3 row(s) affected)
    

    EDIT query that replaces FOR XML PATH with FOR XML RAW, so this should work on SQL Server 2000

    SELECT
        a.*,dt.CombinedValue
        FROM #TableA        a
            LEFT OUTER JOIN (SELECT
                                 c1.RowID
                                     ,STUFF(REPLACE(REPLACE(
                                              (SELECT 
                                                   ', ' + TypeOf as value
                                                   FROM (SELECT
                                                             a.RowID,a.Value1,a.Value2,b.TypeOf
                                                             FROM #TableA                 a
                                                                 LEFT OUTER JOIN #TableB  b ON a.RowID=b.RowID
                                                        ) c2
                                                   WHERE c2.rowid=c1.rowid
                                                   ORDER BY c1.RowID, TypeOf
                                                   FOR XML RAW
                                              )
                                             ,'<row value="',''),'"/>','')
                                       , 1, 2, '') AS CombinedValue
                                 FROM (SELECT
                                           a.RowID,a.Value1,a.Value2,b.TypeOf
                                           FROM #TableA                 a
                                               LEFT OUTER JOIN #TableB  b ON a.RowID=b.RowID
                                      ) c1
                                 GROUP BY RowID
                            ) dt ON a.RowID=dt.RowID
    

    OUTPUT, same as original query

    0 讨论(0)
  • 2020-12-19 08:05

    Have a look at these articles:

    http://dataeducation.com/rowset-string-concatenation-which-method-is-best/

    http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/ (See Phil Factor's cross join solution in the responses - which will work in SQL Server 2000)

    Obviously in SQL Server 2005, the FOR XML trick is easiest, most flexible and generally most performant.

    As far as returning a rowset for each row, if you still want to do that for some reason, you can do that in a stored procedure, but the client will need to consume all the rows in the first rowset and then go to the next rowset and associate it with the first row in the first rowset, etc. Your SP would need to open a cursor on the same set it returned as the first rowset and run multiple selects in sequence to generate all the child rowsets. It's a technique I've done, but only where ALL the data actually was needed (for instance, in a fully-populated tree view).

    And regardless of what people say, doing it client-side is often a very big waste of bandwidth, because returning all the rows and doing the looping and breaking in the client side means that huge number of identical columns are being transferred at the start of each row just to get the changing column at the end of the row.

    Wherever you do it, it should be an informed decision based on your use case.

    0 讨论(0)
提交回复
热议问题