2012-11-30 81 views
0

可以說我有四個表,我想閱讀:合併使用1三個查詢:*關係到一個查詢

客戶

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; 
} 

唯一我可以想到的方式來獲得上述信息是通過使用三個查詢。原因是客戶表和其他每個表之間存在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中的每一行返回一個客戶行。無論如何,我可以將上述三個查詢合併爲一個?

+0

齊格:你寫 「的問題......是我拍三級調用數據庫」。爲什麼這是一個問題?如果您擔心代碼的冗長,請使用ORM框架(如@enno所示)。如果您擔心長期維護,也可以使用ORM框架。如果您擔心_potential_性能問題,請等到您看到實際的性能問題,然後重構(預測性能問題會導致不必要的複雜性)。 – netjeff

回答

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個單獨的查詢花費少很多。

+0

我沒有嘗試過,但問題是父表中的每一行都重複了子表中的每一行。這是不可避免的嗎? – ziggy

+0

所以然後只是從您的查詢中省略這些列。要清楚,您仍然至少需要2個查詢:一個填充您的客戶「標題」信息,然後填充相關數據。 –

+0

我的意思是,例如,customer_name只在結果的第一次迭代中需要,但它將在所有迭代中存在(如果有意義的話),所以列不能被省略。 – ziggy

1

沒有什麼能阻止你迭代和處理連接結果到你的客戶對象。如果您的應用程序足夠複雜,那麼您可以查看ORM框架,這些框架可以爲您解決這個問題。如果您正在使用JavaEE,請查看JPA。

+0

@ziggy是啊,爲什麼不呢。你可以這樣做,通過添加ORDER BY customer_id –

+0

對不起,我不小心刪除了問題,我問我是否應該在迭代結果時存儲該id。 :( – ziggy

+0

@ziggy如果你想從表中提取所有客戶(例如),那麼是的,在做1)使用ID創建客戶對象時迭代通過加入和排序的結果集,2)繼續添加電話/地址如果ID匹配,3)如果ID改變,將客戶對象存儲到您的列表中,爲新ID創建新的客戶對象 - >繼續執行,直到用盡結果集 –

0

使用此查詢並減少呼叫次數。並且,在數據的while循環過程中。

選擇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 AND customer.customer_id = customer_tel_no.customer_id

+0

您可以選擇您的代碼(在編輯答案的同時)並點擊'{}'按鈕。它會將您的代碼4列向右縮進,因此它將作爲代碼顯示。 –