如何在tsql中选择具有某些行优先级的随机行

问题描述

我的问题是此处提出的问题的扩展:How to request a random row in SQL?

扩展名是什么?假设有一个用户表,其结构如下:

id (int) | name | email | phone number (char)

如果我想选择几个随机用户,请执行以下查询:

SELECT TOP @X column FROM table ORDER BY NEWID()

我需要的扩展名是优先给拥有电话号码(不为NULL)的用户。应该随机选择用户,但是应该首先选择具有电话号码(如果有)的用户,并且返回的行总数仍应为@X。

谢谢。

解决方法

您可以在order by子句中添加特定的组件,以将适当的电话号码放在首位,例如,

SELECT TOP @X column 
FROM table 
ORDER BY 
    CASE WHEN [Phone Number] IS NOT NULL THEN 0 ELSE 1 END,NEWID();

这会将所有具有电话号码的用户分类为一个存储桶(0),将没有电话号码的用户分类为另一个存储桶(1)。然后,它们仍然在该存储桶中随机分组。

,

如果我正确执行此操作,则需要两个级别的排序:

select column
from (select top @x * from table order by newid()) t
order by case when phone_number is not null then 0 else 1 end

子查询选择@x个随机行,然后外部查询首先将phone_number不为null的行(如果有的话)放置。

,
SELECT TOP(3)
      *
FROM (
    VALUES
    (1001,'fred','999 999 999'),(2001,'barney','888 888 888'),(3001,'betty',''),(4001,'wilma','')
    ) driver( id,name,phone)
cross apply (
    SELECT
          BINARY_CHECKSUM(phone) x1,BINARY_CHECKSUM(id,phone,NEWID()) x2,ABS(BINARY_CHECKSUM(BINARY_CHECKSUM(phone),NEWID())) x3
        ) ca (x1,x2,x3)
ORDER BY x3 DESC
  id | name  | phone       |        x1 |          x2 |         x3
---: | :---- | :---------- | --------: | ----------: | ---------:
3001 | betty |             |         0 | -1025202521 | 2016765040
1001 | fred  | 999 999 999 | 984285186 |  1620969732 | 1872682014
4001 | wilma |             |         0 | -1149900698 | 1518182428

db 提琴here

请尝试多次运行示例以查看不同的结果。

ABS()BINARY_CHECKSUM()与不同的列一起使用,可以使您找到改变顺序以影响随机性的方法。

请注意,按newid订购时,性能成本较高(0见:https://docs.microsoft.com/en-us/previous-versions/software-testing/cc441928(v=msdn.10)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...