Search code examples
sqlsql-server-2008analyticsaggregate-functions

sql comma delimited list of a column in analytical function


I am using SQL server 2008, and I need to make a common delimeted list of a column. I know how to do it, but I need this time while I use analytical function, I mean I don't want to use group by clause. Since I will also select the records in outer query "where row_num=1"

Here is the query:

SELECT UserId
      ,ProductList
      ,Value
  FROM
  (
SELECT p.UserId 
     ,p.Value
     , ROW_NUMBER()OVER (PARTITION BY p.UserId ORDER BY p.RecordCreateDate asc) AS 'row_num'
     --here I need a solution  OVER (PARTITION BY p.UserId) AS 'ProductList'
  FROM Products p
       INNER JOIN
       Users u
       ON p.UserId = u.Id
       ) result
 WHERE result.row_num = 1

Users data:

Id       Name      ....
 1       John
 2       Anton
 3       Craig

Products data:

Id      UserId      Name     RecordCreateDate   Value
 1           1         a           21.12.2012      10
 2           1         b           11.12.2012      20
 3           1         c           01.12.2012      30
 4           2         e           05.12.2012      40
 5           2         f           17.12.2012      50
 6           3         d           21.12.2012      60 
 7           3         i           31.12.2012      70

I need a result such as:

UserId     ProductList      Value
     1           a,b,c         30
     2             e,f         40
     3             d,i         60

Thanks for your help


Solution

  • Just for completeness. Remove the # symbols for your actual solution.

    SET NOCOUNT ON;
    
    CREATE TABLE #users
    (
        Id INT,
        Name VARCHAR(32)
    );
    
    INSERT #users VALUES
    (1,'John'),
    (2,'Anton'),
    (3,'Craig');
    
    CREATE TABLE #products
    (
        Id INT,
        UserId INT,
        Name VARCHAR(32),
        RecordCreateDate DATE,
        Value INT
    );
    
    INSERT #products VALUES
    (1,1,'a','2012-12-21',10),
    (2,1,'b','2012-12-11',20),
    (3,1,'c','2012-12-01',30),
    (4,2,'e','2012-12-05',40),
    (5,2,'f','2012-12-17',50),
    (6,3,'d','2012-12-21',60), 
    (7,3,'i','2012-12-31',70);
    

    The query:

    ;WITH x AS 
    (
        SELECT UserId, Value, 
            row_num = ROW_NUMBER() OVER 
            (
                  PARTITION BY UserId 
                  ORDER BY RecordCreateDate
            )
            FROM #products
    )
    SELECT
      x.UserId,
      u.Name,
      ProductList = STUFF((
         SELECT ',' + Name
            FROM #Products AS p 
            WHERE p.UserId = x.UserId 
            FOR XML PATH(''), 
            TYPE).value(N'./text()[1]', N'varchar(max)'),1,1,''),
      x.Value
    FROM x
    INNER JOIN #users AS u
    ON x.UserId = u.Id
    WHERE x.row_num = 1;
    

    Then clean up:

    DROP TABLE #users, #products;
    

    Results:

    UserId  Name    ProductList  Value
    1       John    a,b,c        30
    2       Anton   e,f          40
    3       Craig   d,i          60