我有一个搜索应用程序。有 7 个字段(名字、姓氏、电话、街道、城市、商店号码、信用卡号码),用户可以在其中写入参数,它会在数据库中找到他的客户。一切都在 AND 条件下工作,所以当名字是“Andy”而姓氏是“Larkin”时,只会找到 Andy Larkins 等。用户可以将字段留空,这意味着当名字是“Andy”时,它应该会找到所有 Andys 等。数据库如下所示:
“关系”表用于连接人和商店。一个人必须有 1 个地址、1 个商店,可以有多个地址、多个商店并且没有信用卡/多张信用卡。现在,我必须在一个查询中处理所有的过滤,我不能先检查一些条件然后用另一种方式构造查询,我只是没有那个选项。
当我按名字或姓氏搜索时,速度很快(均在 Person 表中),但当我按电话号码或信用卡号码搜索时,会花费很多时间。数据库中有很多数据,但我的查询仍然很糟糕,我不太擅长编写查询,尤其是在 Oracle 中。这是查询:
SELECT
PERSON.personId,
PERSON.firstName,
PERSON.lastName
ADDRESS.street,
ADDRESS.city,
ADDRESS.phoneNumber
FROM
PERSON
LEFT JOIN ADDRESS ON PERSON.personId = ADDRESS.personId,
LEFT JOIN RELATION ON PERSON.personId = RELATION.personId,
LEFT JOIN SHOPS ON RELATION.shopId = SHOPS.shopId
LEFT JOIN CREDITCARDS ON PERSON.personId = CREDITCARDS.personId
WHERE
PERSON.firstName = NVL(?, PERSON.firstName),
PERSON.lastName = NVL(?, PERSON.lastName),
ADDRESS.phoneNumber = NVL(?, ADDRESS.phoneNumber),
ADDRESS.street = NVL(?, ADDRESS.street),
ADDRESS.city = NVL(?, ADDRESS.city),
SHOPS.shopNumber = NVL(?, SHOPS.shopNumber),
CREDITCARDS.creditCardNumber = NVL(?, CREDITCARDS.creditCardNumber);
用户留空的参数作为 NULLS 传递,这就是我使用 NVL 的原因。当我删除所有条件并留下信用卡号时,它会很快,所以我想这意味着所有不必要的条件检查都会减慢查询速度,而且在大多数情况下我真的不需要那个条件检查,它只是以防用户传递某些东西。
如果我可以选择检查条件然后才构建查询,那么我将只添加所需的条件,但我没有该选项。我正在考虑在查询中添加一些“IF”,但我不确定这是否可能,我能找到的只是“IF/CASE WHEN”,但找不到适用于我的案例的任何示例。我也试过这个:
...WHERE (? IS NULL OR (PERSON.firstName = NVL(?, PERSON.firstName))) AND...
这没有帮助,我得到了大量重复的结果(仅在地址或其他方面有所不同 - 一个人可以有多个地址)结果(即使使用“DISTINCT”)。
这不是作业,那个数据库很大,还有很多其他字段,但是我在这里简化了它,那里也有很多数据。感谢您的帮助。
最佳答案
这里有几点需要考虑。
- 注意可能没有意义的查询;例如那些查询信用卡号和地址的。这种性质的查询会落入粉丝陷阱。
- 在数据库中创建引用完整性约束将允许优化器执行连接消除。
- 如果您可以动态构建查询“where 子句”而不是使用 NVL 函数,那么对于优化器来说会好得多。
关于database - 使用多个连接和可选参数进行查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41622441/