将使用1:*关系的三个查询合并到一个查询中

时间:2012-11-30 20:11:09

标签: java sql oracle java-ee jdbc

让我们说我想读四张桌子:

客户

customer_id,    customer_name
1               Joe Bolggs

customer_orders

customer_id, order_no
----------------------------
1       1
1       2
1       3

customer_addresses

customer_id address
----------------------------
1       11 waterfall road
1       23 The broadway

customer_tel_no

customer_id number
----------------------------
1       523423423432
1       234342342343

上面显示的客户信息(对于id = 1的客户)将存储在Java对象中,如下所示

public class Customer{

    String customer_id;
    String customerName;
    ArrayList<String> customerOrders;
    ArrayList<String> customerAddress;
    ArrayList<String> customerTelephoneNumbers;
} 

我能想到获得上述信息的唯一方法是使用三个查询。原因是customer表和每个其他表之间存在1:*关系。为了得到数据,我正在做这样的事情:

Customer customer = new Customer()

String customerSQL = "Select * from customer where customer_id = ?";
statement = getConnection().prepareStatement(contactsQuery);
statement.setString(1,1);
resultSet = statement.executeQuery(); 

while (resultSet.next()){
    customer.customer_id = resultSet.get(1);    //No getters/setters in this example
    customer.customerName = resultSet.get(2);
}

String customerOrdersSQL = "Select * from customer_orders where customer_id = ?";
statement = getConnection().prepareStatement(customerOrdersSQL); 
statement.setString(1,1);
resultSet = statement.executeQuery(); 

customer.customerOrders = new ArrayList();
while (resultSet.next()){
    customer.customerOrders.add(resultSet.getString(2);  // all the order numbers
}


String customerAddressesSQL = "Select * from customer_addresses where customer_id = ?";
statement = getConnection().prepareStatement(customerAddressesSQL ); 
statement.setString(1,1);
resultSet = statement.executeQuery(); 

customer.customerAddresses = new ArrayList();
while (resultSet.next()){
    customer.customerAddresses.add(resultSet.getString(2);  // all the addresses
}


String customerTelSQL = "Select * from customer_tel_no where customer_id = ?";
statement = getConnection().prepareStatement(customerTelSQL); 
statement.setString(1,1);
resultSet = statement.executeQuery(); 

customer.customerTelephoneNumbers = new ArrayList();
while (resultSet.next()){
    customer.customerTelephoneNumbers.add(resultSet.getString(2);  // all the order numbers
}

以上问题是我正在对数据库进行三次调用。有没有办法可以将上面的内容合并到一个查询中?

我无法看到联接是如何工作的,因为例如,customer和customer_orders之间的联接将返回customer_orders中每行的客户行。无论如何,我可以将上述三个查询合并为一个吗?

3 个答案:

答案 0 :(得分:1)

我认为这样的事情会奏效:

SELECT c.customer_id, c.customer_name, o.order_no, a.address, t.number
FROM customer c LEFT JOIN customer_orders o ON c.customer_id = o.customer_id
LEFT JOIN customer_addresses a ON c.customer_id = a.customer_id
LEFT JOIN customer_tel_no t ON c.customer_id = t.customer_id
WHERE c.customer_id = ?

然后,在您的代码中,执行查询后:

while (resultSet.next())
{
    customer.customerOrders.add(resultSet.getString(3));
    customer.customerAddresses.add(resultSet.getString(4));
    customer.customerTelephoneNumbers.add(resultSet.getString(5));
}

当然,这并没有考虑到你将一路上有空值的事实,所以我建议检查空值以确保你没有向数组列表中添加大量垃圾。尽管如此,这可能比3个单独的查询要便宜得多。

答案 1 :(得分:1)

没有什么能阻止您将加入的结果迭代并处理到客户对象中。如果您的应用程序足够复杂,您可以查看ORM框架,这些框架可以帮助您完成这些工作。如果您正在使用JavaEE,请查看JPA。

答案 2 :(得分:0)

使用此查询并减少呼叫次数。并且,在数据循环过程中。

选择customer.customer_id,customer.customer_name,order_no,地址,号码

来自客户,customer_orders,customer_addresses,customer_tel_no

其中customer.customer_id = customer_orders.customer_id 和 customer.customer_id = customer_addresses.customer_id 和 customer.customer_id = customer_tel_no.customer_id