【问题标题】:MSSQL Select Random in Large DataMSSQL 在大数据中随机选择
【发布时间】:2014-12-23 03:10:37
【问题描述】:

我有一个包含超过 100 万条记录的表,我想从该表中选择随机行,但不是从所有记录中选择 - 仅从匹配某些条件的结果中选择随机行。

性能非常重要,所以我不能使用 NEWID 排序然后选择第一个项目。

表结构是这样的:

 ID    BIGINT
 Title NVARCHAR(100)
 Level INT
 Point INT

现在,我写了如下查询:

with 
    tmp_one as
    (
        SELECT
                R.Id as RID 
                FROM    [User] as U
                            Inner Join
                        [Item] as R
                            On  R.UserId = U.Id

                WHERE       ([R].[Level] BETWEEN @MinLevel AND @MaxLevel) 
                        AND ((ABS((BINARY_CHECKSUM(NEWID(),R.Id,NEWID())))% 10000)/100 ) > @RangeOne
    ),
    tmp_two as
    (
        Select  tmp_one.RID as RID
            From    tmp_one
            Where   ((ABS((BINARY_CHECKSUM(NEWID(),RID,NEWID())))% 10000)/100 ) > @RangeTwo
    ),
    tmp_three as
    (
        Select  RID as RID 
            From    tmp_two
            Where   ((ABS((BINARY_CHECKSUM(NEWID(),NEWID())))% 10000)/100 ) < @RangeThree
    )
    Select  top 10 RID
        From    tmp_three

我尝试随机选择10个项目,然后选择其中一个,但是我有一个惊人的问题!!!

有时输出是按项目级别排序的!而且我不想要它(它不是真正随机的)。我真的不知道结果是如何按级别排序的。

请提出一些解决方案,帮助我在高性能中选择随机记录,并且在高迭代范围内随机选择不重复。

【问题讨论】:

  • 您拥有没有 ORDER BY 的 TOP。所以你告诉 SQL Server “我不在乎顺序!”因此,SQL Server 会按照 认为最有效的顺序将数据返回给您。
  • 好的,我怎样才能阻止这种有效的订单并告诉它只使用默认订单而不更改它? (插入顺序)以及为什么在常规选择中不会发生这种情况并选择按插入顺序显示数据?
  • 请点击此处阅读#3:SQL Server Assumptions

标签: sql sql-server tsql


【解决方案1】:

试试这样的。它会从你的表中随机抓取 10 行。

这是伪代码,因此您可能需要修复一些列名以匹配您的真实表。

DECLARE @Random int
DECLARE @Result table
(ID BIGINT,
Title varchar(100),
Level int,
Point int)

declare @TotalRows int
set @TotalRows = (select COUNT(*) From [User] U inner join [Item] R on R.UserID = U.ID)

while (select COUNT(*) from @Result)<10
begin
set @Random = (select floor(RAND() * @TotalRows+1))

insert into @Result
select T1.ID, T1.Title, T1.Level, T1.Point from
(select top (@Random) * From [User] U inner join [Item] R on R.UserID = U.ID) T1
left outer join (select top (@Random) * From [User] U inner join [Item] R on R.UserID = U.ID) T2 on T2.ID = T1.ID
where T2.ID is null


end

select * from @Result

这是它的工作原理。

Select a random number.   For example 47. 
We want to select the 47th row of the table. 
Select the top 47 rows, call it T1. 
Join it to the top 46 rows called T2. 
The row where T2 is null is the 47th row. 
Insert that into a temporary table. 
Do it until there are 10 rows. 
Done.

【讨论】:

    【解决方案2】:

    基于 MSDN 的 Selecting Rows Randomly from a Large Table,而不是您避免使用的:

    select top 10 * from TableName order by newid()
    

    这表明:

    select top 10 * from TableName where (abs(cast((binary_checksum(*) * rand()) as int)) % 100) < 10
    

    它只有更小的逻辑读取和更好的性能。

    【讨论】:

      猜你喜欢
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多