(Обновление: добавлен окончательный запрос.)
(Обновление 2: добавлен один запрос, чтобы избежать временной таблицы.)
Вот сложная часть с использованием рекурсивного CTE плюс окончательный запрос, показывающий «место».
код
DECLARE @cust TABLE (
CustomerID int IDENTITY,
ParticipationCt int
)
DECLARE @list TABLE (
CustomerID int,
RowNumber int
)
INSERT INTO @cust (ParticipationCt) VALUES (5)
INSERT INTO @cust (ParticipationCt) VALUES (8)
INSERT INTO @cust (ParticipationCt) VALUES (1)
INSERT INTO @cust (ParticipationCt) VALUES (3)
INSERT INTO @cust (ParticipationCt) VALUES (4)
SELECT * FROM @cust
;WITH t AS (
SELECT
lvl = 1,
CustomerID,
ParticipationCt
FROM @Cust
UNION ALL
SELECT
lvl = lvl + 1,
CustomerID,
ParticipationCt
FROM t
WHERE lvl < ParticipationCt
)
INSERT INTO @list (CustomerID, RowNumber)
SELECT
CustomerID,
ROW_NUMBER() OVER (ORDER BY NEWID())
FROM t
--<< All rows
SELECT * FROM @list ORDER BY RowNumber
--<< All customers by "place"
SELECT
CustomerID,
ROW_NUMBER() OVER (ORDER BY MIN(RowNumber)) AS Place
FROM @list
GROUP BY CustomerID
Результаты
CustomerID ParticipationCt
----------- ---------------
1 5
2 8
3 1
4 3
5 4
CustomerID RowNumber
----------- -----------
4 1
1 2
1 3
2 4
1 5
5 6
2 7
2 8
4 9
2 10
2 11
2 12
1 13
5 14
5 15
3 16
5 17
1 18
2 19
2 20
4 21
CustomerID Place
----------- -----
4 1
1 2
2 3
5 4
3 5
Одиночный запрос без временной таблицы
Возможно получить ответ с помощью одного запроса, который не использует временную таблицу. Это прекрасно работает, но мне лично больше нравится версия временного стола, чтобы вы могли проверить промежуточные результаты.
Код (одиночный запрос)
;WITH List AS (
SELECT
lvl = 1,
CustomerID,
ParticipationCt
FROM @Cust
UNION ALL
SELECT
lvl = lvl + 1,
CustomerID,
ParticipationCt
FROM List
WHERE lvl < ParticipationCt
),
RandomOrder AS (
SELECT
CustomerID,
ROW_NUMBER() OVER (ORDER BY NEWID()) AS RowNumber
FROM List
)
SELECT
CustomerID,
ROW_NUMBER() OVER (ORDER BY MIN(RowNumber)) AS Place
FROM RandomOrder
GROUP BY CustomerID