SQL-即使存在少于X条记录,也可以检索顶部(X)条记录

SQL-即使存在少于X条记录,也可以检索顶部(X)条记录,sql,random,Sql,Random,在我的应用程序中,有几个地方向用户显示一组随机的X项。用户界面要求显示X个项目。但是,不能保证表中有X项。因此,如果没有X项,我需要用随机重复项填充结果 我需要编写一个基本上是: SELECT TOP(@count) * FROM Things ORDER BY NEWID() 我希望能够向SQL请求X条记录,并且每次都能准确地返回X条记录。有没有一种简单的方法可以在SQL中实现这一点 谢谢。可以在T-SQL中完成: SELECT * FROM ( SELECT TOP(@count) *

在我的应用程序中,有几个地方向用户显示一组随机的X项。用户界面要求显示X个项目。但是,不能保证表中有X项。因此,如果没有X项,我需要用随机重复项填充结果

我需要编写一个基本上是:

SELECT TOP(@count) *
FROM Things
ORDER BY NEWID()
我希望能够向SQL请求X条记录,并且每次都能准确地返回X条记录。有没有一种简单的方法可以在SQL中实现这一点


谢谢。

可以在T-SQL中完成:

SELECT *
FROM (
 SELECT TOP(@count) *
 FROM Things
 ORDER BY NEWID()
) x
UNION ALL
SELECT DummyValuesHere
FROM Numbers
WHERE Numbers.ID <= (@count - (SELECT COUNT(*) FROM Things))
你需要一个数字表。我们只是将所有正确数量的伪行追加到UNION中


现在你知道查询是多么可怕了,考虑一下在应用程序中做这项工作吧。SQL不是用于此类查询的好工具。

好吧,我有一个解决方案,但我仍然认为要求很荒谬。这假设在我的例子中,源表@t至少有一行。如果你有零行,你到底在演示什么

DECLARE @count INT = 17; -- here is whatever your 'X' is; pick any value


DECLARE @t TABLE(i INT);

-- just insert 10 arbitrary values; test with @count = 5, @count = 247, etc.

INSERT @t VALUES(150),(170),(50),(100),(200),(230),(20),(800),(180),(632);

DECLARE @x INT; SELECT @x = COUNT(*) FROM @t;

SELECT TOP (@count) x.* FROM 
(
  -- limit this set to @count:
  SELECT TOP (@count) * FROM @t ORDER BY NEWID()
) AS x 
OUTER APPLY 
(
  -- limit this set the ratio of @count to rows in @t
  -- add one to round up for integer division:
  SELECT TOP (@count/@x+1) * FROM sys.all_objects 
  WHERE @count > @x -- only evaluate this subquery if we don't have enough rows
) AS y
ORDER BY NEWID(); -- need a 2nd ORDER BY in my tests to avoid pockets of same values

帽子提示。

我最终创建了自己的解决方案

DECLARE @count INT = 10; 

DECLARE @ids TABLE(id INT);

WHILE ((SELECT COUNT(*) FROM @ids) < @count)
BEGIN
    INSERT INTO @ids
        SELECT TOP(@count) ID
        FROM Things
        ORDER BY NEWID()
END

SELECT TOP(@count) t.*
FROM Things t
JOIN @ids ON t.ID = [@ids].id

快速浏览表数据有助于解决查询性能问题, 它可以帮助识别重复出现的值、空值和理解数据

我认为Aaron有最好的答案,不过我要说的是,答案是使用TOP。。。NEWID的订单对于大型表有很大的性能问题, 它们至少会导致一次完整的索引聚集扫描或不扫描, 因为顶部是在排序之后完成的,而排序是在 所有记录的新ID

讨论了另一种解决办法 使用二进制校验和,但根据评论似乎有缺陷

另一个简单的解决方案是使用添加到Sql2005中的TABLESAMPLE选项

SELECT * FROM Sales.SalesOrderDetail TABLESAMPLE (1000 ROWS)

然而,它们是其使用的条件 .. 样本不必是单个行级别的真正随机样本。 表的各个页面上的行与同一页面上的其他行不相关。 根据描述和注释,输出似乎不是完全随机的。
而且,输出并不总是具有所需的行数,

您希望SQL做什么?创建新数据?我认为这是一个需要解决的有趣问题。如果我愿意的话,我可以很容易地用C语言完成这项工作。我觉得如果有一种简单的方法可以在sql中实现,并且我只能对DB进行一次调用,那么它将是干净高效的。讽刺是不受欢迎的TOP@countT.*根据T CROSS APPLY sys.allcolumns SAC ORDER BY newid这个应用程序在视图中有几个地方显示了一组随机的X项,它需要的正好是X项。为什么要求DB提供一组随机的X项并期望结果中有X项是如此愚蠢?@Seattleonard其核心问题是有效的,但它没有明确说明填充行应该包含什么?。因此,很容易赢得仇恨,因为确实存在许多可怕的问题。对于我们这些回答很多的人来说,这是令人沮丧的。在这个问题上的仇恨是错误的。很抱歉。试着以一种明确的方式再次询问这个问题。除了我不想要伪值。向用户展示一堆糟糕的数据是愚蠢的。@Seattleonard好吧,你没有说你想展示什么:只要在联盟的第二部分插入你想要的任何东西就行了。你甚至可以从事物中提取回填行。@Seattleonard有人可能会说,再显示第1行、第1行、第2行、第2行、第2行同样愚蠢。在@count=5的情况下,表中只有2行。有人可能会说,但也有人可能会说,距离我很远的人编写的应用程序的要求也很愚蠢@西雅图:你能详细说明他们在始终精确显示n行时看到了什么价值,即使其中包含冗余的重复项?这真的是为了避免将任何逻辑编码到应用程序中,以便它了解实际存在的行数吗?谢谢您给出了问题的实际答案。在我的例子中,我们可以假设至少有一行。为什么要使用WHILE循环呢?你检查过性能了吗?@AaronBertrand谁需要设置逻辑?!?!不要再吝啬了。99.9999%的时候,while循环本质上只是一个运行两次的if语句。一次启动循环,一次退出循环。如果sql有do/while,它将只检查一次。考虑到我愚蠢的要求,我认为这是一个合理的妥协。@Seattleonard重点不是你选择循环结构,而是你选择了循环结构而不是基于集合的解决方案。关系模型是基于集合的,因此使用Aaron提供的基于集合的解决方案将获得最佳性能。此外,给试图帮助你的人打电话不是继续获得帮助的好方法。落选票将会到来
因为在面对其他答案时,您给出了一个不太好的答案。与仅检索10条记录相比,数千条记录的外部应用不会对性能产生影响吗?