如果没有结果,请重复查询

时间:2017-07-03 13:36:12

标签: sql sql-server

如果没有结果,有人可以建议如何重复查询。我正在尝试使用RAND从数据库中生成一个随机人员,但前提是该数字以前未使用过(该信息存储在“allready_drawn”列中)。 此时,当查询超过之前绘制的数字时,由于第二个条件"is null",它不会显示结果。 我需要再次重新运行查询,直到它出现一个数字。

DECLARE @min INTEGER;
DECLARE @max INTEGER;

set @min = (select top 1 id from [dbo].[persons] where sector = 8 order by id ASC);
set @max = (select top 1 id from [dbo].[persons] where sector = 8 order by id DESC);

select 
ordial,
name_surname

from [dbo].[persons]

where id = ROUND(((@max - @min) * RAND() + @min), 0) and allready_drawn is NULL

结果(两种可能的结果):

enter image description here

感谢任何建议,我想提前感谢所有人。

2 个答案:

答案 0 :(得分:1)

试试这个删除“id”过滤器,这样你只需要运行一次

select TOP 1
    ordial,
    name_surname
from [dbo].[persons]
where allready_drawn is NULL
ORDER BY NEWID()

答案 1 :(得分:0)

@gbn这是一个正确的解决方案,但它可能太贵了。对于具有密集键的非常大的表,在最小值和最大值之间随机选择一个键值并重新拾取直到找到匹配也是公平的,并且比排序整个表便宜。

原始帖子中也存在一个错误,因为最小和最大行的选择频率只有其他行的一半,因为每个行都映射到较小的间隔。要修复从@min生成随机数到@max + 1,并截断,而不是舍入。这样您就可以将区间[N,N + 1]映射到N,从而确保每个N的公平机会。

对于这种选择方法,这里是重复的方法,直到找到匹配为止。

--drop table persons
go
create table persons(id int, ordial int, name_surname varchar(2000), sector int, allready_drawn bit)

insert into persons(id,ordial,name_surname,sector, allready_drawn) 
            values (1,1,'foo',8,null),(2,2,'foo2',8,null),(100,100,'foo100',8,null)

go
declare @min int = (select top 1 id from [dbo].[persons] where sector = 8 order by id ASC);
declare @max int = 1+ (select top 1 id from [dbo].[persons] where sector = 8 order by id DESC);


set nocount on
declare @results table(ordial int, name_surname varchar(2000))

declare @i int = 0
declare @selected bit = 0


while @selected = 0
begin
    set @i += 1

    insert into @results(ordial,name_surname)
    select 
    ordial,
    name_surname
    from [dbo].[persons]
    where id = ROUND(((@max - @min) * RAND() + @min), 0, 1) and allready_drawn is NULL

    if @@ROWCOUNT > 0
    begin
       select *, @i tries from @results
       set @selected = 1
    end
end