问题描述
我的问题是此处提出的问题的扩展: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)