В SQL Server 2005+ вы можете использовать этот подход:
;WITH UsersNumbered AS (
SELECT
UserID,
rownum = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID)
FROM Users
)
SELECT u.*
FROM Users u
INNER JOIN UsersNumbered n ON u.UserID = n.UserID AND n.rownum = 2
При условии, что на UserID
существует некластеризованный индекс, это дает немного худший план выполнения, чем ваш подход. Чтобы сделать его лучше (на самом деле, так же, как у вас), вам нужно использовать ... подзапрос, каким бы нелогичным он ни казался:
;WITH UsersNumbered AS (
SELECT
UserID,
rownum = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID)
FROM Users
)
SELECT u.*
FROM Users u
WHERE EXISTS (
SELECT *
FROM UsersNumbered n
WHERE u.UserID = n.UserID AND n.rownum = 2
);
В случае кластерного индекса на UserID
все три решения дают один и тот же план.