Oto wersja pseudo-UNPIVOT który pozwala określić kolejność kolumn (jeśli nazwy kolumn nie sortują według ich pozycji).
SELECT
T.ID,
X.Name
FROM
T
CROSS APPLY (
SELECT TOP 1 Name FROM (
VALUES (1, 'A1', T.A1), (2, 'A2', T.A2), (3, 'A3', T.A3), (4, 'A4', T.A4),
(5, 'A5', T.A5), (6, 'A6', T.A6), (7, 'A7', T.A7), (8, 'A8', T.A8),
(9, 'A9', T.A9)
) X (Pos, Name, Col)
WHERE Col IS NOT NULL
ORDER BY X.Pos DESC
) X;
Jednakże, podczas gdy rzeczywista IO i CPU nie są dużo gorsze niż naturalne metody UNPIVOT (plan wykonanie wygląda źle, ale rzeczywisty wpływ serwer nie jest dużo gorzej), to nie jest najlepszy wykonawca. Proste wyrażenie CASE podane przez @pst jest.
Zakładając nazwy kolumn może być sortowana jak to, że UNPIVOT można uprościć jeszcze bardziej:
SELECT ID, Max(Last)
FROM T UNPIVOT (Value FOR Last IN (A1, A2, A3, A4, A5, A6, A7, A8, A9)) U
GROUP BY ID;
Wreszcie, oto szalona wersja myślałem że niestety wypada gorzej niż inni:
SELECT
T.ID,
Coalesce(
(SELECT 'A9' WHERE T.A9 IS NOT NULL),
(SELECT 'A8' WHERE T.A8 IS NOT NULL),
(SELECT 'A7' WHERE T.A7 IS NOT NULL),
(SELECT 'A6' WHERE T.A6 IS NOT NULL),
(SELECT 'A5' WHERE T.A5 IS NOT NULL),
(SELECT 'A4' WHERE T.A4 IS NOT NULL),
(SELECT 'A3' WHERE T.A3 IS NOT NULL),
(SELECT 'A2' WHERE T.A2 IS NOT NULL),
(SELECT 'A1' WHERE T.A1 IS NOT NULL)
) LastNotNullColumn
FROM T
ORDER BY ID
Teoretycznie silnik mógłby wymyślić plan, który wygląda bardziej jak wersja ekspresyjna CASE, ale tak nie jest. Plan wygląda absolutnie szalenie, z jednym obiektem tabeli na instrukcję select i zajmuje około dwa razy CPU jako wyrażenie CASE.
Wszystkie wersje testowane używają tej samej liczby odczytów logicznych, różniących się tylko procesorem. Przetestowałem 15 000 wierszy.
Wreszcie, nie mogę z czystym sumieniem nie ostrzec, że twój schemat prawdopodobnie nie jest najlepszy. Chociaż nie mogę stwierdzić, jakie są twoje dane, to próbujesz znaleźć ostatnie, prawdopodobnie sugeruje, że kolumny reprezentują czas lub etapy pewnego cyklu życia - i to nie jest poprawny projekt bazy danych. Zamiast tego przechowuj dane niepodzielone. Kiedy nadejdzie czas, że potrzebujesz zestawu wyników, który jest obrócony, możesz PIVOT. I zapytanie o najnowszą wartość na ID staje się nieco prostsze!
Czy mogę powiedzieć "ten schemat wygląda okropnie"? :-) Można to zrobić z warunkowym priorytetem odwrotnym. –