【问题标题】:T-SQL with random returns multiple rows where one is expectedT-SQL 随机返回多行,其中一个是预期的
【发布时间】:2017-08-04 21:55:13
【问题描述】:

考虑以下从表变量中获取随机行的 T-SQL 代码 (MS SQL Server 2014):

DECLARE @priceClasses TABLE (
    RowIndex INT,
    PriceClassID NVARCHAR(MAX))
;

INSERT INTO @priceClasses VALUES
    (0, 'RETAIL')
    ,(1, 'WHOLESALE')
    ,(2, 'WHOLESALE2')
;

DECLARE @priceClassesCount AS INT;
SET @priceClassesCount = (SELECT COUNT(*) FROM @priceClasses);

SELECT 
    PriceClasses.RowIndex,
    PriceClasses.PriceClassID 
FROM
    @priceClasses AS PriceClasses
WHERE
    PriceClasses.RowIndex = ABS(CHECKSUM(NEWID())) % @priceClassesCount;

最后一个SELECT 语句,出于某种原因,有时返回 0 行,有时返回 1、2 或 3 行。

这对我来说没有意义。列的值是唯一的,ABS(CHECKSUM(NEWID())) % @priceClassesCount不能多值,可以吗?

当我声明 RowIndex INT NOT NULL PRIMARY KEY 而不仅仅是 RowIndex INT 时,问题就消失了。有什么想法吗?

【问题讨论】:

  • 您也可以通过 newid() 更改此设置以获取前 1 个订单。
  • @SeanLange 感谢您的想法!

标签: sql sql-server database tsql random


【解决方案1】:

WHERE 子句每行计算一次。这就是NEWID() 的魅力所在。你的案子的悲剧之美。

如果要使用这种方法,不妨将值存储在变量中:

DECLARE @priceClassesCount AS INT;
SET @priceClassesCount = (SELECT COUNT(*) FROM @priceClasses);
SET @RowIndex = 1 + (ABS(CHECKSUM(NEWID())) % @priceClassesCount)

SELECT pc.RowIndex, pc.PriceClassID 
FROM @priceClasses pc
WHERE pc.RowIndex = @RowIndex;

希望RowIndex 没有空白。这可能是您没有得到任何行的另一个原因。

【讨论】:

  • 确实没有差距。问题是,我不能将值存储在变量中,因为现实更复杂(这整个事情是更大查询中的子查询,所以我需要多次获取随机行)。
  • @wh1t3cat1k 。 . .你应该问另一个问题,详细了解你真正想要解决的问题。获取多个随机行与获取一行不同。
  • 我想我不会,知道 NEWID() 是如何工作的,我现在可以自己推断出正确的解决方案。缺少的一点是您指出的 NEWID() 的此功能。谢谢。
  • Modulo (%) 可以返回0 的结果,并且永远不会返回@priceClassesCount。如果RowIndex1 开始,则此查询可能会不时返回零行,并且永远不会返回“最后”行。
【解决方案2】:

要获得一个随机行,您可以这样做

SELECT TOP 1
    PriceClasses.RowIndex,
    PriceClasses.PriceClassID 
FROM
    @priceClasses AS PriceClasses
ORDER BY
    NEWID();

虽然@GordonLinoff 是正确的,但需求有一个更简单的解决方案

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    相关资源
    最近更新 更多