在我的应用程序中,有几个地方会向用户显示一组随机的X项。 UI要求显示正好X项。但是,无法保证表中会有X项。所以,如果没有X项,我需要用随机副本填充结果。
我需要写一个基本上是的查询:
SELECT TOP(@count) *
FROM Things
ORDER BY NEWID()
我希望能够向SQL索取X记录,并且每次都能获得准确的X记录。有没有一种简单的方法可以在SQL中实现这一点?
谢谢。
答案 0 :(得分:8)
嗯,我有一个解决方案,但我仍然认为这些要求很荒谬。这假定源表(在我的情况下,@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
答案 1 :(得分:2)
我最终创建了自己的解决方案。
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
答案 2 :(得分:1)
快速了解表数据有助于解决查询性能问题, 它可以帮助识别重复值,空值并理解数据。
我认为Aaron有最好的答案,但只是提到,使用TOP的答案... ORDER BY NEWID()对于大表有很大的性能问题, 他们至少诱导完整的索引(聚集或非聚集)扫描, 因为TOP是在SORT之后完成的 所有记录的NEWID。
另一个解决方案here 使用BINARY_CHECKSUM,RAND但根据评论似乎有缺陷。
另一个简单的解决方案是使用已添加到Sql2005的TABLESAMPLE选项
SELECT * FROM Sales.SalesOrderDetail TABLESAMPLE (1000 ROWS)
请参阅here
然而,它们是使用它的条件 “..样本不必是单个行级别的真正随机样本。 表的各个页面上的行与同一页面上的其他行不相关。 “ 并且根据描述和注释,输出似乎不是完全随机的。 而且,输出并不总是具有所需的行数see
答案 3 :(得分:0)
可以在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))
你需要一个Numbers
表。我们只需追加(UNION ALL
)正确数量的虚拟行。
现在你看到查询有多可怕,考虑在应用程序中完成这项工作。 SQL不是这种查询的好工具。