zoukankan      html  css  js  c++  java
  • 一个关于SqlServer 中根据概率获取数据的sql 写法

    朋友提出的问题是这样的:

    以下表记录,如保根据比例随机查询单条?

    id           showPercent(展示比例/机率)
    ----        -------
    1            20 (表示20%)
    2            30
    3            50

    呵呵,思索+尝试了一番,应该是可以解决这个问题的

    create table #tmp
    (
     weight int
    );
    insert into #tmp (weight) select 10;
    insert into #tmp (weight) select 20;
    insert into #tmp (weight) select 30;
    insert into #tmp (weight) select 40;

    create table #tmp2
    (
     row_no int identity(1,1),
     x int,
     cnt int default 0
    );

    DECLARE  @i int
    SET @i=0
    WHILE @i<10000
    BEGIN
     SET @i = @i+1;
     with CTE as
     (
      SELECT t.RowId ,t.weight,t.weight AS cnt FROM
      (
       SELECT ROW_NUMBER() OVER(ORDER BY weight) AS RowId,*  FROM #tmp
      ) AS t WHERE RowId =1
      
      union ALL
      
      SELECT  t2.RowId,t2.weight,t2.weight+c.cnt AS cnt FROM
      (
       SELECT ROW_NUMBER() OVER(ORDER BY weight) AS RowId,* FROM #tmp
      ) AS t2 inner join CTE c on c.RowId+1 = t2.RowId 
     )
     
     --SELECT max(cnt)+1 from CTE
     INSERT INTO #tmp2
     select top 1 weight,cnt
     from cte
     where cnt > cast(RAND()*100 as bigint)%(SELECT max(cnt) from CTE)
     order by cnt;

    END

    drop table #tmp

    SELECT COUNT(1)AS 数量,cnt FROM #tmp2 GROUP BY cnt
    drop table #tmp2

    -----解决方案的思路是这样的:

    比如有一个 概率列表 分别为 10%,20%,30%,40%

    那么,根据他们计算的概率权重,应该是 10,30,60,100

    也就是说,我获得一个100以内的随机数,数值区间分布表如下

    0-10 对应概率10%

    10-30 对应概率 20%

    30-60 对应概率 30%

    60-100 对应概率 40%

    所以我们只要获得一个随机数,% 100求模,获得随机数的区间,即可根据该数值获得指定概率的记录

    再延伸一下,即使概率为和不为100,依然可以根据该公式计算对应的概率,

    也就是说,概率列表可以是 10 10 10 10 30 加起来为 70,第一个就是 1/7,最后一个为 3/7

    依次类推,可解决这个问题

    上面那个公式包含了整个完整算法

    实例代码,包含了一个CTE递归合并写法,不难理解

    cast(RAND()*100 as bigint) 表示生成一个100以内的数值,如果和大于一百,可以把这个放大到 10000 或者更高,其实这个就是随机值的获取咯

    运行1w次结果

    出现次数 权重

    1010   10
    1989      30
    2979      60

    4022     100
     

  • 相关阅读:
    删除链表的倒数第N个节点(java实现)
    Java多线程之volatile关键字《一》
    Utils
    分布式和集群
    java RMIC
    Log4j输出终端(Appender)详解
    使用存储过程并返回值与及返回值的获得方法
    groupBy
    group by java实现
    本机Font字体
  • 原文地址:https://www.cnblogs.com/mine/p/2179218.html
Copyright © 2011-2022 走看看