为子孙后代记录所有等级,我们每人只使用1个等级,所以差距是可以的。很抱歉重新提出这个问题,但想问一个关于语法的快速问题。这个解决方案对我们有效(谢谢!)。TSQL中的dt()是什么?但是您想要的是最小值(行数)而不是最大值?另外,假设你不需要特殊人物的行号
为子孙后代记录所有等级,我们每人只使用1个等级,所以差距是可以的。很抱歉重新提出这个问题,但想问一个关于语法的快速问题。这个解决方案对我们有效(谢谢!)。TSQL中的dt()是什么?但是您想要的是最小值(行数)而不是最大值?另外,假设你不需要特殊人物的行号,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,为子孙后代记录所有等级,我们每人只使用1个等级,所以差距是可以的。很抱歉重新提出这个问题,但想问一个关于语法的快速问题。这个解决方案对我们有效(谢谢!)。TSQL中的dt()是什么?但是您想要的是最小值(行数)而不是最大值?另外,假设你不需要特殊人物的行号详细信息,只需要最小结果这确实符合我最初的要求-我最终会使用Sean的答案,因为我们确实需要“临时”数字(不仅仅是最小值或最大值),但我喜欢另一种方法。如果你想要所有的数字,请删除MIN()函数和group by子句,与其他答案相同,这些关系不
为子孙后代记录所有等级,我们每人只使用1个等级,所以差距是可以的。很抱歉重新提出这个问题,但想问一个关于语法的快速问题。这个解决方案对我们有效(谢谢!)。TSQL中的dt()是什么?但是您想要的是最小值(行数)而不是最大值?另外,假设你不需要特殊人物的行号详细信息,只需要最小结果这确实符合我最初的要求-我最终会使用Sean的答案,因为我们确实需要“临时”数字(不仅仅是最小值或最大值),但我喜欢另一种方法。如果你想要所有的数字,请删除
MIN()
函数和group by
子句,与其他答案相同,这些关系不会导致问题吗?难道不能有三个人拥有同样的灵魂吗?@shawnt00,可以有很多特殊的人拥有同样的灵魂。如果有一个特殊的人,它可以拥有与普通人相同的等级。如果有5个特别的人,他们都可以偶然拥有同样的心灵,和普通人一样。要正确地解决这类任务,如果没有这些联系,整个方法应该是不同的。@shawnt00,正确的解决方案是这样的。让我们有O
普通人加S
特殊人。每个普通人有一次机会,每个特殊的人有三次机会。我们应该生成均匀分布在[1..O+S*3]
范围内的O
加S*3
随机数,然后根据得到的数字对所有人进行排序。特殊人物将在这个有序列表中出现3次,普通人只出现一次。我同意你的第二个评论。但是,您只能有三个具有相同MinRN的表,因为您只加入了这三个表。@shawnt00,我在答案中添加了第二个(正确的)变体。
SELECT personID, ROW_NUMBER()
OVER(ORDER BY NEWID()) as RowNumber
FROM folks
personID isSpecial
1 1
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
SELECT personID, isSpecial, row_number
OVER(ORDER BY NEWID()) as RowNumber
FROM folks
personID RowNumber isSpecial
8 1 0
2 2 0
10 3 0
1 4 1
9 5 0
3 6 0
4 7 0
6 8 0
5 9 0
7 10 0
personID MinRowNumber isSpecial rowNumber1 rowNumber2 rowNumber3
8 1 0 1
2 2 0 2
1 3 1 4 7 3
9 5 0 5
3 6 0 6
6 8 0 8
5 9 0 9
7 10 0 10
4 11 0 11
10 12 0 12
SELECT personID, ROW_NUMBER()
OVER(ORDER BY NEWID()) as RowNumber
FROM folks
WHERE isSpecial = 0
UNION ALL
SELECT personID, MAX(RN)
FROM (
SELECT personID, ROW_NUMBER() AS 'RN'
OVER(ORDER BY NEWID()) as RowNumber
FROM folks
WHERE isSpecial = 1
UNION ALL
SELECT personID, ROW_NUMBER()
OVER(ORDER BY NEWID()) as RowNumber
FROM folks
WHERE isSpecial = 1
UNION ALL
SELECT personID, ROW_NUMBER()
OVER(ORDER BY NEWID()) as RowNumber
FROM folks
WHERE isSpecial = 1
)
GROUP BY personID
WITH
cteTally(N) AS (select n from (values (1),(2),(3))dt(n))
select personID
, MAX(RowNumber)
from
(
SELECT personID
, ROW_NUMBER() OVER(ORDER BY NEWID()) as RowNumber
FROM folks f
join cteTally t on t.N <= case when f.IsSpecial = 1 then 3 else 1 end
) x
group by x.personID
WITH
cteTally(N) AS (select n from (values (1),(2),(3))dt(n))
SELECT personID
, ROW_NUMBER() OVER(ORDER BY NEWID()) as RowNumber
FROM folks f
join cteTally t on t.N <= case when f.IsSpecial = 1 then 3 else 1 end
create table folks (personID int, isSpecial int)
insert into folks values (1,1);
insert into folks values (2,0);
insert into folks values (3,0);
insert into folks values (4,0);
insert into folks values (5,0);
insert into folks values (6,0);
insert into folks values (7,0);
insert into folks values (8,0);
insert into folks values (9,0);
insert into folks values (10,0);
select * from folks;
select
personID,
min(rownumber) as min_rownumber
from
(SELECT
personID,
ROW_NUMBER() OVER(ORDER BY NEWID()) as RowNumber
FROM
(select personID from folks
union all
select personID from folks where isSpecial = 1
union all
select personID from folks where isSpecial = 1) u
) r
group by
personID
WITH
CTE_Numbers
AS
(
SELECT Number
FROM (VALUES (1),(2),(3)) AS N(Number)
)
,CTE
AS
(
-- list ordinary people only once
SELECT PersonID,IsSpecial
FROM @T
WHERE IsSpecial = 0
UNION ALL
-- list each special person three times
SELECT PersonID,IsSpecial
FROM @T CROSS JOIN CTE_Numbers
WHERE IsSpecial = 1
)
,CTE_rn
AS
(
SELECT
PersonID,IsSpecial
,ROW_NUMBER() OVER(ORDER BY CRYPT_GEN_RANDOM(4)) AS rn
FROM CTE
)
SELECT
PersonID,IsSpecial
,MIN(rn) AS FinalRank
FROM CTE_rn
GROUP BY PersonID,IsSpecial
ORDER BY FinalRank;
PersonID IsSpecial FinalRank
9 0 1
2 0 2
1 1 3
10 0 4
8 0 5
5 0 6
3 0 7
7 0 9
4 0 10
6 0 12
DECLARE @T TABLE (PersonID int, IsSpecial bit);
INSERT INTO @T(PersonID, IsSpecial) VALUES
(1 , 1),
(2 , 0),
(3 , 0),
(4 , 0),
(5 , 0),
(6 , 0),
(7 , 0),
(8 , 0),
(9 , 0),
(10, 0);
WITH
CTE1
AS
(
SELECT PersonID, IsSpecial,
ROW_NUMBER() OVER(ORDER BY CRYPT_GEN_RANDOM(4)) AS rn
FROM @T
)
,CTE2
AS
(
SELECT PersonID, IsSpecial,
ROW_NUMBER() OVER(ORDER BY CRYPT_GEN_RANDOM(4)) AS rn
FROM @T
)
,CTE3
AS
(
SELECT PersonID, IsSpecial,
ROW_NUMBER() OVER(ORDER BY CRYPT_GEN_RANDOM(4)) AS rn
FROM @T
)
,CTE_All
AS
(
SELECT
CTE1.PersonID
,CTE1.IsSpecial
,CTE1.rn AS rn1
,CTE2.rn AS rn2
,CTE3.rn AS rn3
,CA.MinRN
FROM
CTE1
INNER JOIN CTE2 ON CTE2.PersonID = CTE1.PersonID
INNER JOIN CTE3 ON CTE3.PersonID = CTE1.PersonID
CROSS APPLY
(
SELECT MIN(A.rn) AS MinRN
FROM (VALUES (CTE1.rn), (CTE2.rn), (CTE3.rn)) AS A(rn)
) AS CA
)
SELECT
PersonID
,IsSpecial
,CASE WHEN IsSpecial = 0
THEN rn1 -- a person is not special, he gets random rank from the first run only
ELSE MinRN -- a special person, he gets a rank that is minimum of three runs
END AS FinalRank
,rn1
,rn2
,rn3
,MinRN
FROM CTE_All
ORDER BY FinalRank;
PersonID IsSpecial FinalRank rn1 rn2 rn3 MinRN
8 0 1 1 1 1 1
6 0 2 2 7 2 2
5 0 3 3 5 6 3
1 1 3 9 3 4 3
4 0 4 4 6 3 3
7 0 5 5 9 10 5
3 0 6 6 8 9 6
2 0 7 7 2 8 2
10 0 8 8 10 5 5
9 0 10 10 4 7 4