使用多个连接和可选参数进行查询

时间:2017-01-12 20:32:19

标签: database oracle performance

我有一些搜索应用程序。有7个字段(名字,姓氏,电话,街道,城市,商店编号,信用卡号码),用户可以在其中编写参数,并在数据库中找到他的客户。一切都与AND条件一起工作,所以当名字'Andy'而且姓氏'Larkin'只会找到Andy Larkins等。用户可以留空字段,这意味着当名字是'Andy'时它应该找到所有的Andys等数据库都是这样的:

enter image description here

'关系'表用于连接人和商店。人必须有1个地址,1个商店,可以有多个地址,多个商店,没有信用卡/多个信用卡。现在,我必须处理单个查询中的所有过滤,我之前无法检查某些条件,然后以另一种方式构造查询,我只是没有那个选项。

当我用名字或姓氏搜索时,它很快(都在人员表中),但是当我通过电话号码或信用卡号码搜索时 - 这需要花费很多时间。数据库中有很多数据,但我的查询仍然很糟糕,我不擅长编写查询,特别是在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')。

这不是家庭作业,数据库是很多其他领域,但我在这里简化了,那里也有很多数据。谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

这里要考虑一些事情。

  1. 注意可能没有意义的查询;例如那些查询信用卡号和地址的人。这种性质的质疑陷入了一个风扇陷阱。
  2. 在数据库中创建参照完整性约束将允许优化器进行连接消除。
  3. 如果您可以构建查询" where子句"那么优化器会好得多。动态地,而不是使用NVL功能。

答案 1 :(得分:0)

商店的嵌套选择可能会提高性能,特别是考虑到它的外部连接。下面的查询应足以让您了解。

关于重复数据删除 - 这很难,因为你选择了Id而'distinct'无济于事。您可能必须使用语法分组,这可能会使查询变得更慢。

如果可以在客户端上进行排序,则可能有助于提高性能。如果由于扇出关系数据而分组返回的数据量很大并且分组不是一个好的选择,那么创建存储过程可能是最好的选择,因此大部分工作都是在数据库上进行的,并且通过线路完成最少的数据

<div class="container-fluid">
    <div class="row">
        <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-xs-12">
            <table>
                <tr>
                    <td>ID</td>
                    <td>First Name</td>
                    <td>Last Name</td>
                    <td>Title</td>
                    <td>Address1</td>
                    <td>City</td>
                    <td>State</td>
                    <td></td>
                </tr>
                <tr ng-repeat="currentContact in contacts">
                    <td class="col-lg-1 col-md-1 col-sm-1 col-xs-2 col-xs-1">
                        {{currentContact.id}} 
                    </td>
                    <td class="col-lg-1 col-md-1 col-sm-1 col-xs-2 col-xs-1">
                        <input type="text" ng-model="currentContact.firstName" ng-show="editId != undefined">
                        <span ng-hide="editId != undefined">{{ currentContact.firstName }}</span>
                    </td>
                    <td class="col-lg-1 col-md-1 col-sm-1 col-xs-2 col-xs-1">
                        <input type="text" ng-model="currentContact.lastName" ng-show="editId != undefined">
                        <span ng-hide="editId != undefined">{{ currentContact.lastName }}</span>
                    </td>
                    <td class="col-lg-2 col-md-2 col-sm-2 col-xs-2 col-xs-2">
                        <input type="text" ng-model="currentContact.title" ng-show="editId != undefined">
                        <span ng-hide="editId != undefined">{{ currentContact.title }}</span>
                    </td>
                    <td class="col-lg-2 col-md-2 col-sm-2 col-xs-2 col-xs-2">
                        <input type="text" ng-model="currentContact.Address1" ng-show="editId != undefined">
                        <span ng-hide="editId != undefined">{{ currentContact.Address1 }}</span>
                    </td>
                    <td class="col-lg-1 col-md-1 col-sm-1 col-xs-2 col-xs-1">
                        <input type="text" ng-model="currentContact.City" ng-show="editId != undefined">
                        <span ng-hide="editId != undefined">{{ currentContact.City }}</span>
                    </td>
                    <td class="col-lg-1 col-md-1 col-sm-1 col-xs-2 col-xs-1">
                        <input type="text" ng-model="currentContact.State" ng-show="editId != undefined">
                        <span ng-hide="editId != undefined">{{ currentContact.State }}</span>
                    </td>

                    <td class="col-lg-3 col-md-3 col-sm-3 col-xs-3 col-xs-3">
                        <span ng-click="editContact($index)" ng-hide="editId != undefined">Edit</span>
                        <span ng-click="save($index)" ng-show="editId != undefined">Save</span>
                        <span ng-click="deleteContact($index)"> | Delete</span>
                    </td>
                   
                </tr>
            </table>           
            <button type="button" data-ng-click="goToHome();" class="btn btn-warning">Cancel</button> 	

        </div>
    </div>

</div>