He Who Shall Not Be Named He Who Shall Not Be Named - 3 months ago 5
SQL Question

SQL - pivot three rows into three columns with static column names?

I'm relatively new to SQL, but I have a query,

select top 3 LoginDateTime from UserLogins where Username = 'John Doe' order by LoginDateTime desc


That returns the three most recent logins.

How would I go about pivoting the query so that I end up with a result where each date is in its own column, and where the column headers are '1st', '2nd', and '3rd'?

Thanks!

ADDENDUM: The query is running on MS SQL Server targetting specifically the content of the result (which may change in future to include more than just the top three logins). It could even become a case where the column titles themselves have to change over time, so static titles (as opposed to programmatically generated) would be the ideal solution.

Answer

You have to have something to pivot on to identify which column should get what value, so you could create a row_number and then pivot that data. here is an example with test data.

DECLARE @UserLogins AS TABLE (LoginDateTime DATETIME, UserName VARCHAR(20))

    INSERT INTO @UserLogins (LoginDateTime, UserName)
    VALUES
    (GETDATE(),'John Doe')
    ,(GETDATE() -1,'John Doe')
    ,(GETDATE() -2,'John Doe')
    ,(GETDATE() -3,'John Doe')
    ,(GETDATE() -4,'John Doe')

    ;WITH cteRowNum  AS (
        SELECT TOP (3)
           UserName
           ,LoginDateTime
           ,RowNum = ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY LoginDateTime DESC)
        FROM
           @UserLogins
        WHERE
           UserName = 'John Doe'
        ORDER BY
           LoginDateTime DESC
    )

    SELECT
        UserName
        ,[1] as [1st]
        ,[2] as [2nd]
        ,[3] as [3rd]
    FROM
        cteRowNum
        PIVOT (
           MAX(LoginDateTime)
           FOR RowNum IN ([1],[2],[3])
        ) p

Note the SELECT TOP(3) and order by isn't necessary I just kept it there as a limiter. If there are less than 3 logins the column(s) for that count will be null, more than 3 just don't get displayed.....