我试图从表中随机选择一行。我很好奇为什么下面的两个陈述不起作用:
select LastName from DataGeneratorNameLast where id = (ABS(CHECKSUM(NewId())) % 3)+1
select LastName from DataGeneratorNameLast where id = cast(Ceiling(RAND(convert(varbinary, newid())) *4) as int)
两个语句随机返回1行,无行或多行。对于我的生活,我无法弄清楚为什么。只在查询中添加前1只能解决多行的问题 - 但不会返回任何行。
是的我可以通过选择top 1并按newid()排序来做同样的事情。但是为什么这不起作用的谜团让我发疯。
关于我为什么要多行回来的想法?
以下是我用来选择的表格:
Create Table dbo.DataGeneratorNameLast
(
[Id] [int] IDENTITY(1,1) NOT NULL,
LastName varchar(50) NOT NULL,
)
Go
insert into DataGeneratorNameLast (LastName) values ('SMITH')
insert into DataGeneratorNameLast (LastName) values ('JOHNSON')
insert into DataGeneratorNameLast (LastName) values ('Booger')
insert into DataGeneratorNameLast (LastName) values ('Tiger')
答案 0 :(得分:2)
newid()
会对与其进行比较的每一行进行评估,从而生成不同的数字。要做你想做的事,你应该在select之前将随机值生成一个变量,然后引用变量。
Declare @randId int = (abs(checksum(newid())) % 3) + 1;
select LastName from DataGeneratorNameLast where id = @randId;
正如马丁在评论中所说的那样。 Rand()的行为会有所不同,每次查询只会被评估一次。
答案 1 :(得分:0)
如果该表至少有一行该查询将返回一行,则必须使用一行。
select TOP (1) LastName
from DataGeneratorNameLast
ORDER BY NEWID()
请注意,如果表具有大量行,则此解决方案可能会很慢。
关于select LastName from DataGeneratorNameLast where id = @Rand
- 此解决方案不保证存在带id的行。甚至IDENTITY列也可以包含间隙。如果您确实需要一行,请进行初步检查IF EXISTS (select * from DataGeneratorNameLast where id = @Rand) SELECT ...
答案 2 :(得分:0)
我有一个类似的问题并通过将ID作为主要密钥来修复它。
每行计算NEWID()。如果没有主键,除了表扫描之外没有访问模式,并且会针对每一行检查过滤器,因此为每一行计算不同的值,然后您会得到许多行匹配。
使用密钥,搜索可用,因此谓词计算一次并用作搜索的搜索参数。