2012-10-31 65 views
1

更新:我用我生產的問題顯示的SQL查詢,但如果你想看到的另一種方法來此,歡迎您閱讀整個線程,使用SQL與UNIONmysql查詢連接:段或子節中的頁面,是否有更好的替代GROUP BY的替代方法?

我我已經做了實驗,並將結果集用於內容搜索,但我想確保它的性能是最好的。

我有一個命名的節表持有2個水平部分,即第1級(一個部分)和第2級(一個子段),在鄰接表模型

SECTIONS: id, parent_id, name 

我查詢該表兩次以獲得列的排列

sec_id, sec_name, subsec_id, subsec_name 

(這是這樣我就可以創建一個像/ SECTION_ID/subsection_id URI鏈接)

現在我加入一個單獨的名爲表頁面,其中一個頁面可與一節或第(兩者不能同時)通過現場SECTION_ID

-- columns to return 
SELECT 
s.id as section_id, 
s.name as section_name, 
ss.id as subsection_id, 
ss.parent_id as subsection_parent_id, 
ss.name as subsection_name, 
p.section_id as page_section_id, 
p.name as page_name 

-- join SECTIONS into Sections and SubSections 
FROM 
(select id, name from sections where parent_id=0) as s 

LEFT JOIN 
(select id, parent_id, name from sections where parent_id!=0) as ss 

ON 
ss.parent_id = s.id 

-- now join to PAGES table 
JOIN 
(select id, section_id, name from pages where active=1) as p 

ON 
(
p.section_id = s.id 
OR 
p.section_id = ss.id 
) 
-- need to use GROUP BY to eliminate duplicate pages 
GROUP BY p.id 

我得到的結果集中重複的網頁,所以我用GROUP BY pages.id以便移除重複的,但它會使性能稍微有點兒。

你能否提出一種更好的方法來消除重複?

我想過在SECTIONS連接中創建一個包含部分ID或子部分ID(取決於行的類型 - 部分或子部分)的列,然後使用它與PAGES section_id關聯,所以不會有重複的行,但我不知道如何去做。

感謝

+0

您是否試圖檢索給定的頁面(節或子節)?換句話說,你的輸入是一個(部分或子部分)ID,不是嗎?對不起,我有點困惑,因爲在查詢中沒有看到WHERE子句。 – RandomSeed

+0

尚無標準。我試圖從PAGES表中創建一組行,然後可以搜索其內容(當我在後面添加一個標準時)。我只是將我現在需要的列組裝到最終結果集中。謝謝 –

+0

我以爲我可以創建一個視圖從這個搜索反對,但我剛剛學到了mysql不喜歡在FROM子句中使用派生表的視圖 - 即時學習:( –

回答

0

這會是長期:(

需要注意的是我,因爲它的性能是差了我原來嘗試使用GROUP沒有到底使用這種方法BY

我不得不修改PAGES表的數據表設計,以包含一個新列來保存頁面所屬的子部分的ID,所以現在PAGES表中有列表示它屬於的部分,並且該小節也是。該結構修改僅用於測試,並且我沒有在最終版本中使用它。

這是我在2個查詢之間使用UNION的概念創建的查詢。

SELECT 
* 
FROM 
    pages AS p 
JOIN 
-- create derived table of sections and subsections 
    (-- separate query to get sections (parent id = 0) 
    SELECT 
     s.id AS page_sec_id, 
     s.id AS sec_id, 
     s.name AS sec_name, 
     NULL AS subsec_id, 
     NULL AS subsec_name, 
     s.parent_id AS parent_id 
    FROM 
     sections AS s 
    WHERE 
     s.parent_id = 0 
    UNION 
    -- separate query to get subsection (parent id != 0) 
    SELECT 
     ss.id AS page_sec_id, 
     ss.parent_id AS sec_id, 
     -- need to get section name, so had to use weird subquery 
     (SELECT name FROM sections WHERE parent_id =0 AND id = ss.parent_id) AS sec_name, 
     ss.id AS subsec_id, 
     ss.name AS subsec_name, 
     ss.parent_id AS parent_id 
    FROM 
     sections AS ss 
    WHERE 
     ss.parent_id != 0 
    ) AS sss 

ON 
    -- specify how PAGES table is joined to this derived table of sections and subsections 

    -- pages linked to sections only 
     (p.section_id = sss.sec_id AND p.subsection_id = 0 AND sss.parent_id = 0) 
     OR 
    -- pages linked to subsections only 
     (p.section_id = sss.sec_id AND p.subsection_id = sss.subsec_id) 

此UNION查詢中使用 0.0388秒 爲5行頁數和4行分段/小分段, 與其中使用 0原始查詢。0017秒, 所以我堅持原來的如上所示在我的問題。順便說一句,在我的開發環境中,mysql運行在P3 Katmai 450 Mhz 256 RAM上,迫使我編寫高效查詢:)

感謝您的閱讀,如果您有其他想法&評論請添加。

1

你得到重複的網頁,因爲你不區分與從那些涉及到Level-2部分第1級欄目頁面。相反,把頁面分開兩組:

-- pages related to a level-2 section 
SELECT 
    p.id, p.section_id, p.name, 
    l1.id AS section_id, l1.name AS section_name, 
    l2.id AS subsection_id, L2.name AS subsection_name 
FROM pages AS p 
JOIN sections AS l2 ON (
    l2.id = p.section_id AND 
    l2.parent_id <> 0 
) 
JOIN section AS l1 ON (
    l1.id = l2.parent_id 
) 
WHERE active = 1 

UNION 

-- pages related to a level-1 section 
SELECT 
    p.id, p.section_id, p.name, 
    l1.id AS section_id, l1.name AS section_name, 
    NULL, NULL -- do not join with sub-sections, so as to avoid duplicates 
JOIN sections AS p_ss ON (
    p_ss.id = p.section_id AND 
    p_ss.parent_id = 0 
) 
WHERE active = 1 
+0

謝謝你的答案,它沒有不能直接工作,但我能夠使用你的概念創建2個獨立的查詢並將它們結合在一起,但是性能比我使用GROUP BY的原始查詢更差,所以我現在要堅持使用該版本。發佈我的嘗試使用你的版本是爲了讀這個的其他人。 –