【问题标题】:Can you use random numbers in a CASE statement (SQL Server 2016)您可以在 CASE 语句中使用随机数吗(SQL Server 2016)
【发布时间】:2018-01-30 20:07:54
【问题描述】:

我试图构造一个适合更大 SELECT 的 CASE 语句。我希望每一行单独解析(每行使用不同的随机数),但是如果有意义的话,在评估特定行中的 case 语句时随机数是相同的。

我试过了

    SELECT 
    [Player name]
    ,[Stake]
    ,[current jackpot]

         ,CASE

         WHEN 
         rand() < 0.23
         THEN
         'Win'
         WHEN
         rand() BETWEEN 0.23 AND 0.89
         then
         'Lose'
         when
         rand() >= 0.89
         then
         'Jackpot'
         else
         'other'
         end as [outcome]
...

但我有时会得到“其他”结果的事实告诉我,每个 WHEN 都在创建一个不同的随机数来评估。我也不能在开始时声明一个全局随机数并使用它,因为每一行都应该单独解析。

【问题讨论】:

  • 你可以声明一个变量并保存这个 rand() 值并在你的查询中使用它
  • 您可以使用 rownumber 之类的内容作为种子,这将使每一行都相同,但其他行不同。然后可能将Minute(Now()) 添加到行中,以便在运行之间有所不同
  • 上述重复并不是真正的重复。在这种情况下,OP 在SELECT 中多次引用相同的随机数。这会有所不同。
  • 当 rand_value
  • @ventik - 不幸的是,T-SQL 无法保证它将评估函数/表达式的次数与该函数/表达式以文本形式出现在查询中的次数。

标签: sql sql-server random


【解决方案1】:

每次调用RAND() 时,都会给出一个随机种子,因为您没有指定一个。只需给RAND() 一个种子,它就会保持不变。

select 
    case when 1 = 1 then rand(4) end
    ,case when 2=2 then rand(4) end

或者使用列值...

select 
    case when 1 = 1 then rand(someColumn) end
    ,case when 2=2 then rand(someColumn) end

【讨论】:

  • 这不是意味着每一行都有相同的结果吗?
  • 是的,如果你给它一个种子,不,如果你使用一个行唯一的列。
【解决方案2】:

可以。但是,rand() 每次查询仅评估一次,而不是每行一次。相反,你想用newid() 做点什么。但是,因为您在 CASE 中多次引用该值,这会带来挑战。一种方法是:

SELECT . . .
        (CASE WHEN rnd < 0.23 THEN 'Win'
              WHEN rnd < 0.89 THEN 'Lose'
              WHEN rnd >= 0.89 THEN 'Jackpot'
              ELSE 'Other' -- impossible
         END) as [outcome]
FROM (SELECT t.*, rand(convert(varbinary, newid())) as rnd
      FROM t
     ) t

【讨论】:

  • 我认为您的意思是“rand() 不是每行只评估一次”,否则原始查询将起作用。
  • @DStanley 。 . .我的意思是“每次查询一次”。谢谢你的澄清。
【解决方案3】:

另一个选项是交叉应用

示例

Select [Player name]
      ,[Stake]
      ,[current jackpot]
      ,[OutCome] = case when b.randV<0.23 then 'win'
                        when b.randV between 0.23 and 0.89 then 'lose'
                        when b.randV>=0.89 then 'Jackpot'
                        else 'other' end
 From  YourTable
 Cross Apply (values (rand(cast( NewID() as varbinary )))) B(randV)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    • 2017-05-07
    • 1970-01-01
    • 2016-04-02
    相关资源
    最近更新 更多