我有一个函数来尝试将部分数据与数据库行匹配。 如果参数为非null,我希望它找到匹配项;如果它为null,则应忽略该参数。 如果其中一个参数具有值但未找到匹配项,则查询不返回任何行。
在伪代码中,这就是它的发展方式:
get all rows where:
param_a matches col_a when param_b is not null else don't check this column
AND param_b matches col_b when param_b is not null else don't check this column
AND param_c matches col_c when param_c is not null else don't check this column
AND param_d matches col_d when param_d is not null else don't check this column
AND param_e matches col_e when param_e is not null else don't check this column
我现在做的是什么:
SELECT * FROM table
WHERE nvl(param_a, col_a) = col_a
AND nvl(param_b, col_b) = col_b
AND nvl(param_c, col_c) = col_c
AND nvl(param_d, col_d) = col_d;
等...它有效,但我不确定它是最好的选择。一位同事建议我使用
SELECT * FROM table
WHERE (param_a = col_a or param_a is null)
AND (param_b = col_b or param_b is null)
AND (param_c = col_c or param_c is null)
AND (param_d = col_d or param_d is null);
由于这用于Web应用程序中的自动完成功能,因此在用户键入时会执行很多查询。快速是必不可少的。首先过滤最严格的列以减少要处理的行数。
这些选项中的任何一个都更可取吗?如果没有,你会怎么做?
修改
我写的问题是通用的,但是把它放在上下文中:在这种情况下它是用于地址的。 param_a
实际上是邮政编码,param_b
街道名称等...该函数获取用户编写的字符串(例如:999 Random St,Fakestate,Countryland,131ABD)并在其上调用一个尝试的过程拆分它并返回一个包含地址,城市,国家等的表格......由select语句使用(这是问题的主题)。
答案 0 :(得分:2)
我相信第二种解决方案更好。它允许Oracle跳过评估colA / B / C / D,相应的参数为null。
但是,如果动态构建查询,它会更清晰,更快。
例如,无论是在sql中还是在编程语言中,您都可以执行以下操作:
whereClause = 'WHERE 1 = 1'
IF paramA is not null
then whereClause += ' AND param_a = col_a'
else if paramB is not null
then whereClause += ' AND param_b = col_b'
etc...
对于索引,我只会索引常用的列组合。有太多的组合可以覆盖它们。选择能让你获得最大回报的那些。
答案 1 :(得分:1)
如果你想尝试打字速度,那么我建议采用以下方法。为每个参数组合创建单独的查询。这是总共24个查询,其中包含where
条款,如:
WHERE param_a = col_a
WHERE param_b = col_b
. . .
WHERE param_a = col_a and param_b = col_b
. . .
WHERE param_a = col_a and param_b = col_b and param_c = col_c and param_d = col_d
然后,预先编译这24个查询。
然后根据参数的当前状态选择适当的查询。
我还要添加索引,至少:
table(param_a, param_b, param_c, param_d)
table(param_b, param_c, param_d, param_a)
table(param_c, param_d, param_a, param_b)
table(param_d, param_a, param_b, param_c)
这将至少涵盖具有一个参数的所有情况。您可能希望包含其他参数的其他索引。