and*_*ss6 1 sql-server sql-server-2017
我有一个查询,它首先计算要返回的行数,如果它低于限制,则返回这些行,否则不返回任何内容。
对于上下文:我有一张地图,仅在某个缩放级别后才显示一些点。但是,我的用户现在希望地图只要屏幕上有空间就显示点,而不是具有预定义的最小缩放级别。这意味着现在每当他们在地图上移动时,我都会有两个查询,而不是一个:一个是知道有多少项目,另一个是实际返回它们。负载可能会翻倍。我想过这样做:
SELECT p.ACOLUMN, p.ANOTHERCOLUMN, p.LATITUDE, p.LONGITUDE
FROM table p
where p.LATITUDE < @latMax)
and p.LATITUDE > @latMin)
and p.LONGITUDE < @lngMax)
and p.LONGITUDE > @lngMin)
and (SELECT count(*)
FROM table
where LATITUDE < @latMax
and LATITUDE > @latMin
and LONGITUDE < @lngMax
and LONGITUDE > @lngMin)) < 200 -- example limit value
Run Code Online (Sandbox Code Playgroud)
查看实际执行计划,我看到 SQL Server 2017 在同一个索引上搜索了两次:
它当然也在两个搜索中读取相同数量的行。有没有办法删除那些重复的搜索?或者是否有另一种更理想的方式来做我正在尝试的事情?
我并不是说一直到申请的往返。在这种情况下,我认为存储过程是“应用程序”的一种形式。
DECLARE @c int;
SELECT @c = COUNT(*) FROM dbo.table WHERE ...;
IF @c < 200
BEGIN
SELECT cols FROM dbo.table WHERE ...;
END
Run Code Online (Sandbox Code Playgroud)
如果应用程序总是期望一个空的或非空的结果集,你可以这样做:
DECLARE @c int;
SELECT @c = COUNT(*) FROM dbo.table WHERE ...;
SELECT TOP (CASE WHEN @c <= 200 THEN @c ELSE 0 END) cols
FROM dbo.table WHERE ...;
Run Code Online (Sandbox Code Playgroud)
是的,您必须读取表两次(在少于 200 行的情况下;TOP (0) 应该短路),但我没有看到避免这种情况的方法,除非您可能首先将行转储到临时结构中(如果您的 I/O 比您的网络快得多,但您仍然最多只能写入 201 行,这可能仍然比在网络上移动更多行要好得多):
SELECT TOP (201) cols INTO #f FROM dbo.table WHERE ...;
IF @@ROWCOUNT <= 200
BEGIN
SELECT cols FROM #f;
END
DROP TABLE #f;
Run Code Online (Sandbox Code Playgroud)
你也可以试试这个,但我不确定结果会比你原来的更好,这完全取决于 SQL Server 是否认为它不必两次实现 CTE:
;WITH c AS
(
SELECT cols, rn = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM dbo.table WHERE ...
)
SELECT cols FROM c WHERE NOT EXISTS (SELECT 1 FROM c WHERE rn > 200);
Run Code Online (Sandbox Code Playgroud)