where条件下的Sql和获取的行数

where条件下的Sql和获取的行数,sql,firebird2.5,Sql,Firebird2.5,您好,当前我发现自己陷入了困境,如果有解决方案: 假设我们有一个具有字段User\u id、Building\u id的表Users 表值: user_id | building_id ------- ----------- 1 | 1 2 | 1 3 | 2 4 | 2 5 | 2 我们做出选择 Select * from users where building_id = 1 这将获得2行 Select * from use

您好,当前我发现自己陷入了困境,如果有解决方案:

假设我们有一个具有字段User\u id、Building\u id的表Users

表值:

user_id | building_id
-------   -----------
1       | 1
2       | 1
3       | 2
4       | 2
5       | 2
我们做出选择

Select * from users where building_id = 1
这将获得2行

Select * from users where building_id = 2
这将获得3行

Select * from users 
  where (:modus = 1 and building_id = 1) or 
        (:modus = 2 and building_id = 2)
如果我通过:modus=1,它能卖多少线??它读5行,但显示2行

所以问题是,如何使sql中的参数不会读取所有数据,而只显示其中的一部分

更新1(视觉结果): IBExpert中的结果:

普通SQL

带参数的SQL,传递Modus=1

两种情况下的视觉效果:

更新2(真实数据库结果): 非参数建筑=1

如预期的那样12

按预期阅读12


非参数建筑=2

按预期获取5924

按预期阅读5924


参数化,其中参数=1,因此建筑=1

正如您在右上角看到的,获取的金额为12

但在性能分析中,它是5936


使用参数化查询时,Firebird优化器会在准备时而不是执行时决定计划。据我所知,内部Firebird不知道这两个参数是相同的(据我所知,内部Firebird只有位置参数而没有命名参数!)。这意味着Firebird准备了一个计划,该计划将评估这两种情况,因此它将执行这两种情况的所有读取

我假设你的情况比你的问题更复杂,所以像
building_id=:modus
building_id=CASE:modus WHEN 1 WHEN 1 WHEN 2 WHEN 2 END
这样的解决方案是行不通的


您可以尝试
UNION
这两个查询,如果发现条件的计算结果为false,则查询执行可能不会实际读取两个UNION流之一的数据页。

您能定义回迁的含义吗?从SQL客户机API透视图获取的是从服务器检索到的行,使用该定义,如果只显示2行,则只获取了2行(当然,除非客户机执行附加过滤);我不认为这就是你所说的抓取。不知道如何定义这一点,我们是你的IBExpert,它有一个性能分析,在那里它有索引和非索引的读取。你当前的查询正在按照你的预期工作-可能;问题是SQL 1)并没有遵循短路逻辑,实际上,主要是因为2)几乎每个RDBMS都有一个优化器,它寻找返回数据的“最佳”路径。智能优化器能够(但不能保证)基本上忽略“始终为假”条件(即,将
1
传递到
:modus=2
)。你不能直接控制这件事。它有时适用于小数据集上的简单查询;任何大的东西,你都可以使用动态SQL。@ClockworkMuse我知道SQL本身工作正常。但只是试图优化它,这样它就不会进行数千次读取,只是为了找到需要显示的两行,关于动态SQL,主要问题是我们使用的过程中,您不能更改任何内容,或者我错了吗?对于这样一个简单的查询?它可能会表现得像你想要的那样,并给出一个好的计划。对于一些复杂的问题,表中的数据分布不均匀,并且有很多选项?开始掷骰子,有时你赢,有时他们会出现蛇眼。显然,SQLServer对这类事情有一些相当令人讨厌的警告。你说你不能改变程序是什么意思?许多动态SQL通常在用户定义的过程中执行。这并不是说这个查询需要的不仅仅是
BUILDING\u ID
的替换变量。