【问题标题】:selecting random value from column based on distinct values根据不同的值从列中选择随机值
【发布时间】:2017-05-19 13:23:24
【问题描述】:

我在表中有以下数据:-

| item    | rate |
-------------------
| a       | 50   |
| a       | 12   |
| a       | 26   |
| b       | 12   |
| b       | 15   |
| b       | 45   |
| b       | 10   |
| c       | 5    |
| c       | 15   |

我需要一个返回以下输出的查询:

| item no | rate |
------------------
| a       | 12 |  --from (26 , 12 , 50)
| b       | 45 | --from (12 ,15 , 45 , 10)
| c       | 5  | --from (5 , 15)

即 item_no 应该是不同的并且具有随机的一个速率值..

提前致谢

【问题讨论】:

    标签: sql sql-server random distinct-values


    【解决方案1】:

    一种方法是使用以item 作为分区的行号窗口函数。然后在每个分区内使用ORDER BY NEWID()生成随机排序,任意保留每个item分区的第一行。

    SELECT t.item,
           t.rate
    FROM
    (
        SELECT item,
               rate,
               ROW_NUMBER() OVER(PARTITION BY item ORDER BY NEWID()) AS rn
        FROM yourTable
    ) t
    WHERE t.rn = 1
    

    【讨论】:

      【解决方案2】:

      这里NEWID()用于分区生成随机排序,
      在 partition 中,它会保留每个 item 的第一行。

      with cte as
          (
      
              SELECT item,
                     rate,
                     ROW_NUMBER() OVER(PARTITION BY item ORDER BY NEWID()) AS rn
              FROM #Table1
              )
              select item,rate from cte where rn=1
      

      【讨论】:

      • 最好在代码中包含一些上下文/解释,因为这会使答案对 OP 和未来的读者更有用。
      【解决方案3】:
      WITH
      CTE
      AS
      (
          SELECT DISTINCT
              item
          FROM T
      )
      SELECT
          CTE.item
          ,A.rate
      FROM
          CTE
          CROSS APPLY
          (
              SELECT TOP(1) 
                  T.rate
              FROM T
              WHERE T.item = CTE.item
              ORDER BY CRYPT_GEN_RANDOM(4)
          ) AS A
      ;
      

      (item) include (rate) 上的索引会有所帮助。

      【讨论】:

      • 谢谢,@Vladimir,您的查询提供的结果比其他查询快 3 倍。感谢您的所有回复...
      • @speedyraz,很高兴您发现我的回答很有用。这种方法与row_number 的相对性能将取决于您的数据分布(每个项目有多少费率)和可用索引。
      【解决方案4】:

      尝试此查询一次。

      select * into #temp  from (
              SELECT 'a' item,50 rate 
              UNION ALL
              SELECT 'a',12  
              UNION ALL
              SELECT 'a', 26 
              UNION ALL
              SELECT 'b',12  
              UNION ALL
              SELECT 'b', 15 
              UNION ALL
              SELECT 'b',10 
              UNION ALL
              SELECT 'c',5  
              UNION ALL
              SELECT 'c',15 )as a
      
          select * from (
          select *,row_number()over(partition by item  ORDER BY newid() )as runm from #temp
          ) as a
          where runm=1
      

      注意:上面的查询每次都会给出新的输出,因为 newid() 会为每次执行生成一个新的 id。

      【讨论】:

        【解决方案5】:
        ; WITH tb( item, rate)AS(
            SELECT 'a',50 UNION
            SELECT 'a',12  UNION
            SELECT 'a', 26 UNION
            SELECT 'b',12  UNION
            SELECT 'b', 15 UNION
            SELECT 'b',10 UNION
            SELECT 'c',5  UNION
            SELECT 'c',15 
            ) 
            SELECT * FROM (
                SELECT *,ROW_NUMBER()OVER( PARTITION BY item ORDER BY NEWID())  AS rn FROM tb
            ) t WHERE t.rn=1
        

        【讨论】:

          猜你喜欢
          • 2021-10-28
          • 2021-01-11
          • 1970-01-01
          • 2017-03-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多