2014-11-04 33 views
-1

我有三個我正在存儲的主要項目:Articles,Entities和Keywords。這使得5個表格:基於兩個表關係的SQL頂級記錄

article { id } 
entity {id, name} 
article_entity {id, article_id, entity_id} 
keyword {id, name} 
article_keyword {id, article_id, keyword_id} 

我想獲得包含TOP X關鍵字+實體的所有文章。我可以在entity_id/keyword_id上通過一個簡單的羣組獲得頂級X關鍵字實體。

SELECT [entity|keyword]_id, count(*) as num FROM article_entity 
GROUP BY entity_id ORDER BY num DESC LIMIT 10 

我該如何獲得所有與頂級實體和關鍵字有關的文章?

這是我的想象,但我知道它不工作,因爲由限制article_id返回的實體組。

SELECT * FROM article 
WHERE EXISTS (
    [... where article is mentioned in top X entities.. ] 
) AND EXISTS (
    [... where article is mentioned in top X keywords.. ] 
); 
+0

如果你喜歡,可以考慮下列行爲這個簡單的兩步過程:1.如果您還沒有這樣做,提供適當的DDL(和/或sqlfiddle),這樣我們就可以更方便地複製問題。 2.如果您還沒有這樣做,請提供與步驟1中提供的信息相對應的所需結果集。 – Strawberry 2014-11-19 00:47:33

+1

@Strawberry,您能不能從通知複製/粘貼告訴用戶放入DLL並轉到SQL小提琴。通過提供的信息,這些流利的人可以弄清楚,我知道我看過很多這些粘貼評論。 – DRapp 2014-11-19 02:42:13

+0

我提供了一個答案,另一個提到我可能誤解了你的想法,但不相信我做了。讓我知道如果我的目標是你正在尋找什麼...謝謝 – DRapp 2014-11-19 13:31:48

回答

2

如果我理解你正確的目標該查詢將查找與前10個實體中的一個以及前10個關鍵字中的一個關聯的文章。如果是這種情況,則下面的查詢應該這樣做,通過要求返回的文章在前10個實體集合和前10個關鍵字集合中都匹配。

請試試看。

SELECT a.id 
FROM article a 
INNER JOIN article_entity ae ON a.id = ae.article_id 
INNER JOIN article_keyword ak ON a.id = ak.article_id 
INNER JOIN (
    SELECT entity_id, COUNT(article_id) AS article_entity_count 
    FROM article_entity 
    GROUP BY entity_id 
    ORDER BY article_entity_count DESC LIMIT 10 
) top_ae ON ae.entity_id = top_ae.entity_id 
INNER JOIN (
    SELECT keyword_id, COUNT(article_id) AS article_keyword_count 
    FROM article_keyword 
    GROUP BY keyword_id 
    ORDER BY article_keyword_count DESC LIMIT 10 
) top_ak ON ak.keyword_id = top_ak.keyword_id 
GROUP BY a.id; 

的缺點在兩個子查詢頂級實體/關鍵字使用一個簡單的limit 10是,它不會處理關係,所以如果十一關鍵字只是作爲第十它仍然不會得到那樣受歡迎選擇。這可以通過使用排名函數來解決,但afaik MySQL沒有內置任何內容(例如Oracle或MSSQL中的RANK()窗口函數)。

我設置了一個樣本SQL Fiddle(但使用較少的數據點和limit 2,因爲我很懶)。

+0

這看起來像我想要做的。我想唯一的其他事情就是在大量文件的情況下,根據大多數匹配進行某種排序。例如,在你的查詢中,我只需要添加一個'a.id,COUNT(*)num FROM',然後添加'ORDER BY num DESC'。 [SQL小提琴](http://sqlfiddle.com/#!2/5e9ade/2) – Xeoncross 2014-11-19 15:16:02

+0

@Xeoncross這似乎是一個聰明的修改,可能你可能想用'LIMIT'來減少返回的行數。 – jpw 2014-11-22 22:12:38

1

我帶着這幾個步驟

TL;博士這顯示了所有從上面的文章(4)關鍵字和實體:

這裏有一個fiddle

select 
    distinct article_id 
from 
(
select 
    article_id 
from 
    article_entity ae 
    inner join 
    (select 
     entity_id, count(*) 
    from 
     article_entity 
    group by 
     entity_id 
    order by 
     count(*) desc 
    limit 4) top_entities on ae.entity_id = top_entities.entity_id 
union all 
select 
    article_id 
from 
    article_keyword ak 
    inner join 
    (select 
     keyword_id, count(*) 
    from 
     article_keyword 
    group by 
     keyword_id 
    order by 
     count(*) desc 
    limit 4) top_keywords on ak.keyword_id = top_keywords.keyword_id) as articles 

說明:

這從查找頂部X實體的努力開始。 (4似乎工作的數量,我想在小提琴協會的數量)

我不想在這裏選擇文章,因爲它扭曲的羣體,你想專注於頂級實體。 Fiddle

select 
    entity_id, count(*) 
from 
    article_entity 
group by 
    entity_id 
order by 
    count(*) desc 
limit 4 

然後我從這些頂級實體中選擇了所有文章。 Fiddle

select 
    * 
from 
    article_entity ae 
    inner join 
    (select 
     entity_id, count(*) 
    from 
     article_entity 
    group by 
     entity_id 
    order by 
     count(*) desc 
    limit 4) top_entities on ae.entity_id = top_entities.entity_id 

很明顯,對於關鍵字來說,同樣的邏輯需要發生。查詢然後union在一起(fiddle)和不同的文章ID從工會拉。

這將爲您提供與頂部(x)實體和關鍵字有關的所有文章。

+0

@Xeoncross我更新了我的查詢,並給出了幾個解釋,包括SQL小提琴鏈接。我相信這是你需要的答案。查詢可能會縮短,我會考慮這一點,但希望對結果有所反應。 – paqogomez 2014-11-18 23:15:00

0

這得到前10名關鍵字文章也是前10名的實體。你可能不會得到10條記錄回來,因爲它是可能的文章僅滿足的條件之一(頂實體,但不是頂級的關鍵字或頂部關鍵字,但不是頂級實體)

select * 
from article a 
inner join 
       (select count(*),ae.article_id 
       from article_entity ae 
       group by ae.article_id 
       order by count(*) Desc limit 10) e 
on a.id = e.article_id 
inner join 
       (select count(*),ak.article_id 
       from article_keyword ak 
       group by ak.article_id 
       order by count(*) Desc limit 10) k 
on a.id = k.article_id 
+0

「實體」和「關鍵字」表不包含重複項目。他們每個實體和關鍵字只使用一次,因此子查詢中的COUNT(*)不合理。也許你打算在'entity_article'或'keyword_article'表上做一個計數?這些可能有多個結果來計數。 – Xeoncross 2014-11-18 20:34:41

+0

我根據您的反饋更新了我的答案。在子查詢中,您可以使用映射表,因爲這是真正的計數,但我將它們加入到相應的表中以防您想驗證 – Abercrombieande 2014-11-18 20:46:30

+0

看起來您的查詢[does not compile](http://sqlfiddle.com /#!2/e97ca5/10)。另外,我相信你只會用這個查詢給出10個最關鍵的文章。而不是來自前10個關鍵字/實體的文章 – paqogomez 2014-11-18 23:32:25

2

不知道您正在使用的數據量,我會首先建議您在文章表上分別有兩個存儲列,用於計算實體和關鍵字。然後通過觸發器添加/刪除每個觸發器,更新相應的計數器列。這樣,您不必在每次需要時都進行燃燒查詢,尤其是在基於Web的界面中。然後,您可以從由E + K計數降序排列的文章表中進行選擇,並使用它來完成,而不是常常子查詢基礎表。

現在,這就是說,其他建議有點類似於我發佈的內容,但它們似乎都在爲每組限制10條記錄。讓我們把這個場景放入圖片​​中。假設你有1-20篇文章,其中包括10,9和8個實體以及1-2個關鍵詞。然後第21-50條有相反的... 10,9,8個關鍵字和1-2個實體。現在,您的文章51-58有7個實體,7個關鍵詞共有14個合併點。由於實體只會返回符合條件的1-20條記錄和關鍵字記錄21-50,所以這些查詢都不會被捕獲。第51-58條將在名單上如此之低,即使它的總數是14,也不會被考慮。

要處理這個問題,每個子查詢都是一個完整的查詢,專門用於文章ID和它的計數。 article_ID的簡單排序,因爲它是連接到主文章表的基礎。

現在,如果可用,coalesce()將獲得計數,否則爲0並將這兩個值一起添加。從這一點開始,應用限制時,首先排序結果的數量最高(因此可以獲得場景樣本文章51-58以及其他一些數據)。

SELECT 
     a.id, 
     coalesce(JustE.ECount, 0) ECount, 
     coalesce(JustK.KCount, 0) KCount, 
     coalesce(JustE.ECount, 0) + coalesce(JustK.KCount, 0) TotalCnt 
    from 
     article a 
     LEFT JOIN (select article_id, COUNT(*) as ECount 
         from article_entity 
         group by article_id 
         order by article_id) JustE 
      on a.id = JustE.article_id 
     LEFT JOIN (select article_id, COUNT(*) as KCount 
         from article_keyword 
         group by article_id 
         order by article_id) JustK 
      on a.id = JustK.article_id 
    order by 
     coalesce(JustE.ECount, 0) + coalesce(JustK.KCount, 0) DESC 
    limit 10 
+1

我認爲你觸及一個有效選擇適合一組而不是另一組的文章的問題,但我也認爲你可能會誤解其他查詢(或者至少是我的)是如何工作的。子查詢返回10個最常見的實體/文章,並且整個查詢選擇兩個集合中至少有一個匹配的文章,因此只要條件滿足,它就永遠不會限制返回的文章數量。我認爲這是OP想要的(獲得關鍵字和實體頂部的文章),儘管我可能會誤解。 – jpw 2014-11-19 13:18:57

+0

@jpw,我對於OP的要求有不同意見。希望他們會迴應我們各自的問題作任何澄清,但我明白你在這兩個類別中的最高點......你的限制過程可能仍然是錯誤的。 10 ent + 1 kw vs 5 ent + 11 kw ...在您的ent結果集中不會找到11kw。 – DRapp 2014-11-19 13:22:53

+0

讓我們同意尊重地不同意:)如果以「10 ent + 1 kw」表示實體排名爲10,關鍵詞排名第一,則選擇它,而第五個最常見ent +第11個最常見kw的組合不會像第11個kw並不在前十名中,但我以某種方式給人的印象是,這不是你所說的,而是它應該是限制的匹配ent/kw的總數(這樣16總共應該選擇總共11個匹配的文章),這就是我的解釋不同的地方。 – jpw 2014-11-19 13:33:03