2009-08-05 66 views
0

我有一個數據庫有幾個表,其中5個專用於特定的發佈類型。這5箇中的每一個都與狀態表和人員表具有一對多關係。所有這些表都使用獨特的「pubid」捆綁在一起。我有一個視圖,其中包括pubid(所有5種類型)及其關聯的關鍵字。當用戶執行關鍵字搜索並且結果跨越這5個發佈類型表中的多個時,我真的不知道如何處理它。如何處理多個「一對多」關係?

如果只有一個單一的出版物類型(所以只是一個表有一個1->很多),這將是很容易與嵌套連接來完成的,是這樣的:

SELECT * FROM articles 
    INNER JOIN status ON articles.spubid = status.spubid 
    INNER JOIN people ON articles.spubid = people.spubid 
    WHERE people.saffil = 'ABC' ORDER BY people.iorder, articles.spubid; 

在該示例'文章'是我提到的5個表格之一,具有1->多種關係。讓我們說關鍵字搜索帶來的結果,包括文章,書籍和文件。我怎樣才能達到與許多不同的表格相同的目標?如果我想知道如何在這種情況下使用JOIN,那麼笛卡爾積很大,我認爲將其解析爲可用格式的開銷太大。在這種情況下我有什麼其他選擇?

+0

五個表格是否具有相同的模式?或者,您是否真的希望從五個表中選擇A,B,...,Z,其中選定的字段A-Z位於五個模式的交集中? – 2009-08-05 20:21:13

+0

目前正在制定一些涉及views/mviews的解決方案 - 稍後會再提供一份報告/解決方案。 – 2009-08-07 15:59:36

回答

2

它們爲什麼在單獨的表格中?列是不同的?你想要返回哪些列(從來沒有在生產中使用select *,尤其是連接),它們在查詢中的不同類型之間有什麼不同?

如果你能得到的列是相同的,我建議你使用UNION ALL。即使通過在union語句的每個部分中提供所需的所有內容(對於表集不具有的那些列,賦予null值),也可以獲得所需的內容。簡化代碼如下:

SELECT articlename, articlestatus, author, ISBN_Number 
FROM articles 
    INNER JOIN status ON articles.spubid = status.spubid 
    INNER JOIN people ON articles.spubid = people.spubid 
WHERE people.saffil = 'ABC' 
UNION ALL 
SELECT papername, paperstatus, author, null 
FROM papers 
    INNER JOIN status ON papers.spubid = status.spubid 
    INNER JOIN people ON papers.spubid = people.spubid 
WHERE people.saffil = 'ABC' 
+0

不幸的是,每個表格之間的列確實有所不同,並且要列出我們想要返回的所有內容(每個表格有近50列)會非常糟糕,幾乎不可能讀取。 – 2009-08-05 20:18:57

+0

如果您從對象瀏覽器中拖動列名稱,確實不那麼困難。說實話,你需要考慮哪些你不需要,例如連接字段在多個表中重複,不應該全部返回;這只是浪費帶寬。) – HLGEM 2009-08-05 21:21:04

0

也許你可以爲每個5種類型(vwBook,vwArticle等)

的創建意見,您正在搜索,或者叫成一個存儲過程,將使用的關鍵字使用所有5次,你扔在它。 5個結果中的每一個都可以存儲在存儲過程中的表變量中。

修改,當然,如你所見。以下是一個廣泛的筆畫示例:

create proc MySearch 

@MySearchTerm varchar(50) 

AS 
    DECLARE @SearchResultsTABLE 
    (
    Type  varchar(10) -- the view you found the result in. 
    ,ID  int -- the primary key of the Book record. whatever you want to link it back to the original 
    ,FoundText varchar(512) 
    --etc 
    ) 

    INSERT INTO @SearchResults(Type, ID, FoundText) 
     SELECT 'Articles', ID, SomeKeyField 
     FROM vwArticle 
     WHERE SomeKeyField LIKE '%' + @MySearchTerm + '%' 

    INSERT INTO @SearchResults(Type, ID, FoundText) 
     SELECT 'Book', ID, SomeKeyField 
     FROM vwBook 
     WHERE SomeKeyField LIKE '%' + @MySearchTerm + '%' 

    --repeat as needed with the 3 other views that you'd build 

    SELECT * FROM @SearchResults 
2

您可以創建一個視圖,它是所有各種表的聯合。棘手的一點是確保所有UNIONed查詢都具有相同的字段,因此您需要在每個查詢中存留幾個。下面是隻有兩個表一個簡單的例子:

CREATE VIEW AllTables AS 
    SELECT Afield1, Afield2, NULL as Bfield1, NULL as Bfield2 FROM Atable 
    UNION 
    SELECT NULL as Afield1, NULL as Afield2, Bfield1, Bfield2 FROM Btable; 

你可以在必要時使用NULL以外的東西作爲存根值,當然。然後你對視圖運行查詢。如果您需要根據發佈類型更改格式,可以將發起表作爲視圖的一部分(即,添加"'magazine' AS publication_type"或類似於您的每個選擇的內容)。

0

我真的不喜歡這裏的餐桌設計。不過,我猜從頭開始重新設計整個數據庫有點太過分了。

鑑於表設計,我認爲你將不得不去與UNION並指定每個表中的列。我知道這是一個怪物,但是當你設計具有「幾乎」相似的許多列的表時,會發生這種情況。

和HLGEM是對的。在永久存儲的查詢中使用「select *」是非常危險的。

+0

是的一個聯盟已被證明是一個可行的選擇,我同意yo8u A.L.我也不關心這個設計。我將要採用的解決方案(今天測試)是從5個表格(也可能是人員表格)中創建一個物化視圖,以便我可以進行單個聯接,這應該非常簡單。 – 2009-08-07 15:48:09

0

我們最終創建了一個非常複雜的視圖,其中包含1-many表作爲視圖中的數組列。這允許在單個視圖上執行單個查詢並返回所有所需的數據。視圖定義非常複雜,但它像冠軍一樣工作,真正的技巧是使用PostgreSQL中的ARRAY()函數。