A more general solution (i.e., N columns) is to unpivot the columns into rows, and then you can use the window function to obtain the group maximum value for each set of columns of the "row". However, you will need some kind of key for each row, so the maximum can be applied in different ways (to allow the assembly of the source rows). I did this by adding a Guid surrogate via newId() . Note that this returns the NAME column with the highest value in each row:
WITH MyTableWithRowId AS ( SELECT newId() AS Id, * FROM MyTable ), Unpivoted AS ( SELECT Ndx, Id, col, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY col DESC) AS Rnk FROM MyTableWithRowId tbl UNPIVOT ( col for Ndx in(col1, col2, col3) ) p ) SELECT Ndx FROM Unpivoted WHERE Rnk = 1
SqlFiddle here
Change, just enter "1, 2, 3" not the column name (col1, col2, col3)
According to @Giorgi's comment, if you really want a (one base) column position in each row, you can join the DMV, for example INFORMATION_SCHEMA.COLUMNS , to find the sequence number, although that would be a terribly fragile IMO strategy.
WITH MyTableWithRowId AS ( SELECT newId() AS Id, col1, col2, col3 FROM MyTable ), TheOrdinalPositionOfColumns AS ( SELECT COLUMN_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'MyTable' ), Unpivoted AS ( SELECT Ndx, Id, col, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY col DESC) AS Rnk FROM MyTableWithRowId tbl UNPIVOT ( col for Ndx in(col1, col2, col3) ) p ) SELECT topoc.ORDINAL_POSITION AS ColumnOrdinalPosition FROM Unpivoted JOIN TheOrdinalPositionOfColumns topoc ON Unpivoted.Ndx = topoc.COLUMN_NAME WHERE Rnk = 1;
Updated Giorgi column names script