Return some rows in columns

  • I have data for individuals and all the sports they are involved in. I need to return the user information on one row and then the sports they are involved in (up to 3) as additional columns. Here is sample data to represent what I'm working with:

    CREATE TABLE #example

    (

    name VARCHAR(20),

    city VARCHAR(20),

    entryDate DATETIME,

    sport VARCHAR(30)

    )

    INSERT INTO #example

    (name, city, entryDate, sport)

    VALUES

    ('Aaron', 'Gladstone', '8/27/2007', 'Track - Mens'),

    ('Aaron', 'Gladstone', '8/27/2007', 'Track - Mens - Indoor'),

    ('Aaron', 'Gladstone', '8/27/2007', 'Cross Country - Mens'),

    ('Bob', 'Plain', '9/1/2010', 'Wrestling'),

    ('Chris', 'Milwaukee', '1/15/2015', 'Baseball'),

    ('Chris', 'Milwaukee', '1/15/2015', 'Football'),

    ('Doug', 'Richmond', '5/22/2003', 'Volleyball'),

    ('Doug', 'Richmond', '5/22/2003', 'Cross Country - Womens'),

    ('Doug', 'Richmond', '5/22/2003', 'Track - Womens'),

    ('Doug', 'Richmond', '5/22/2003', 'Track - Womens - Indoor')

    What I need to return should look like this (I'm using the | symbol to separate the fields in the example) :

    Name | City | Entry Date | Sport 1 | Sport 2 | Sport 3

    Aaron | Gladstone | 8/27/2007 | Track - Mens | Track - Mens - Indoor | Cross Country - Mens

    Bob | Plain | 9/1/2010 | Wrestling

    Chris | Milwaukee | 1/15/2015 | Baseball | Football

    Doug | Richmond | 5/22/2003 | Volleyball | Cross Country - Womens | Track - Womens

  • WITH cteSports AS (

    SELECT * ,sn = ROW_NUMBER() OVER (PARTITION BY name ORDER BY sport)

    FROM #example

    )

    SELECT

    cte.name

    , cte.city

    , cte.entryDate

    , sport1 = MAX(CASE WHEN cte.sn = 1 THEN cte.sport ELSE NULL END)

    , sport2 = MAX(CASE WHEN cte.sn = 2 THEN cte.sport ELSE NULL END)

    , sport3 = MAX(CASE WHEN cte.sn = 3 THEN cte.sport ELSE NULL END)

    FROM cteSports AS cte

    GROUP BY cte.name, cte.city, cte.entryDate;

  • I wanted to mention that this table structure doesn't follow 1st normal form?

    If this is a database of your own design, I would suggest updating your tables to do so. This would mean, at minimum creating a Player and Sport table, as well as a link table between Player and Sport due to the Many to Many relationship.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Thanks! This looks like it will do the trick. Just need to incorporate it with the actual table structure in the database.

  • This isn't my database design, however, the actual database itself is in 1st Normal form. To get a quick and easy example I posted this knowing I'd have to take any suggestions and retrofit them to the actual database I'm using. Good point, however, for future reference to go a little further in the quick example for temp data.

  • ehlinger (1/9/2017)


    This isn't my database design, however, the actual database itself is in 1st Normal form. To get a quick and easy example I posted this knowing I'd have to take any suggestions and retrofit them to the actual database I'm using. Good point, however, for future reference to go a little further in the quick example for temp data.

    That's fine, I just wanted to make sure 🙂

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • My suggestion would be to use a PIVOT clause:

    WITH cteSports AS (

    SELECT * ,sn = ROW_NUMBER() OVER (PARTITION BY name ORDER BY sport)

    FROM #example

    )

    SELECT name, city, entryDate

    , [1] AS sport1

    , [2] AS sport2

    , [3] AS sport3

    FROM cteSports

    PIVOT (MAX(sport) FOR sn IN ([1],[2],[3])) AS pvt

    Why? Because it's probably more efficient and designed to do this kind of operation :-).

  • JJMEIJER (1/10/2017)


    My suggestion would be to use a PIVOT clause:

    WITH cteSports AS (

    SELECT * ,sn = ROW_NUMBER() OVER (PARTITION BY name ORDER BY sport)

    FROM #example

    )

    SELECT name, city, entryDate

    , [1] AS sport1

    , [2] AS sport2

    , [3] AS sport3

    FROM cteSports

    PIVOT (MAX(sport) FOR sn IN ([1],[2],[3])) AS pvt

    Why? Because it's probably more efficient and designed to do this kind of operation :-).

    Jeff Moden ran a series of tests of a crosstab vs a pivot[/url], and, at that time, the crosstab performed better in the vast majority of cases. Admittedly, that was several years ago, and they may have improved the performance of the pivot function.

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA

  • Thanks for your reply, I use the pivot quite often for management reporting so any insight is welcome.

    Regards, JJ

Viewing 9 posts - 1 through 8 (of 8 total)

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