2009-12-30 47 views
0

我正在讀一本書,作者在這裏談論了在一個步驟中獲取一行+所有鏈接的父行。就像提取一個訂單+所有的項目一次。好吧,聽起來不錯,但真的:我從來沒有看到SQL中可能會要求 - 可以說 - 一個訂單+ 100個項目?這個記錄集怎麼樣?我是否會得到包含訂單和項目表的合併字段的101行,其中100行對於訂單字段有很多空值,而一行對於項目字段有很多空值?這是要走的路嗎?還是有更酷的東西?我的意思是......我從來沒有聽說過將數組提取到一個字段上?如何一次獲取對象圖?

回答

3

一個簡單連接會做的伎倆:

SELECT  o.* 
,   i.* 
FROM  orders o 
INNER JOIN order_items i 
ON   o.id = i.order_id 

的將返回一個排在ORDER_ITEMS每一行。返回的行由orders表中的所有字段組成,並連接到order_items表的所有字段(從字面上來說,表中的記錄已連接,即它們通過記錄連接組合)

So如果訂單具有(id,order_date,customer_id)和order_items(order_id,product_id,price),則上述結果將由具有(id,order_date,customer_id,order_id,product_id,price)的記錄組成

有一件事你需要意識到,只要有一個「主」有兩個不同的「細節」表,這種方法就會崩潰。讓我解釋。

在orders/order_items示例中,orders是master,order_items是detail:order_items中的每一行都屬於或依賴於訂單中的一行。反之亦然:訂單表中的一行可以在order_items表中包含零個或多個相關行。連接條件

ON o.id = i.order_id 

確保只有相關的行合併,並返回(留出的條件將retturn來自這兩個錶行的所有可能的組合,假設該數據庫將允許你忽略連接條件)

現在,假設您有一位主人有兩個詳細信息,例如,作爲主客戶的客戶和作爲detail1和customer_phone_numbers的客戶訂單。假設你想檢索一個特定的客戶以及所有的訂單和所有的電話號碼。你可能會寫:

SELECT  c.*, o.*, p.* 
FROM  customers    c 
INNER JOIN customer_orders   o 
ON   c.id     = o.customer_id 
INNER JOIN customer_phone_numbers p 
ON   c.id     = p.customer_id 

這是有效的SQL,並且將執行(asuming表和列名到位) 但問題是,它會給你一個垃圾結果。假設你有客戶與兩個數量級(1,2)和兩個電話號碼(A,B)如果你把這些記錄:

customer-data | order 1 | phone A 
customer-data | order 2 | phone A 
customer-data | order 1 | phone B 
customer-data | order 2 | phone B 

這是垃圾,因爲它表明有1階和手機之間的一些關係數字A和B以及訂單2和電話號碼A和B.

更糟糕的是,這些結果可能會以記錄數完全爆炸,極大地損害了數據庫性能。

因此,JOIN非常適合將已知深度(客戶 - >訂單 - >訂單_項目)的層次結構「扁平化」爲只包含每個明細項目的主要項目的大表格。但是提取相關項目的真實圖形是可怕的。這是SQL設計方式的直接結果 - 它只能輸出標準化表而不重複組。這是對象關係映射器的存在方式,它允許對象定義可以從關係數據庫中存儲和檢索從屬對象的多個依賴集合,而不會像程序員那樣失去理智。

1

這通常通過JOIN子句完成。這不會導致很多NULL值,但是父行的許多重複值。

另一種選擇是,如果您的數據庫和編程語言支持它,它將在一個連接中返回兩個結果集 - 一個爲相關行選擇另一個父行。