2017-01-02 103 views
0

我有兩個表格(主題和術語)和第三個表格,用於我的兩個實體之間的多對多關係。從MySQL數據計算加權分數的函數?

每個稱爲bagging的關係都有一個源(文本)和一個權重(int在0和100之間)。同一對(主題詞)可以有幾個裝袋(不同的來源),每個都有不同的重量。

現在,當我詢問的話題,找出什麼是它最好的條件(更重),我非常想與計算重量爲唯一值:

  • 100的權重是指這個項目是在最大
  • 幾個重量爲同一對(不同的源)權衡比單對更
  • 沒有「負」重量

這裏是數據庫模式:

| TOPIC 
+-------+------------------+------+-----+---------+----------------+ 
| Field | Type    | Null | Key | Default | Extra   | 
+-------+------------------+------+-----+---------+----------------+ 
| id | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| label | varchar(255)  | NO | UNI | NULL |    | 
| wtext | varchar(40)  | YES |  | NULL |    | 
+-------+------------------+------+-----+---------+----------------+ 

| TERM 
+-------+---------------------+------+-----+---------+----------------+ 
| Field | Type    | Null | Key | Default | Extra   | 
+-------+---------------------+------+-----+---------+----------------+ 
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment | 
| label | varchar(255)  | NO | UNI | NULL |    | 
| slug | varchar(255)  | NO |  | NULL |    | 
+-------+---------------------+------+-----+---------+----------------+ 

| BAGGING 
+----------+---------------------+------+-----+---------+----------------+ 
| Field | Type    | Null | Key | Default | Extra   | 
+----------+---------------------+------+-----+---------+----------------+ 
| id  | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| topic_id | int(11) unsigned | NO | MUL | NULL |    | 
| term_id | bigint(11) unsigned | NO | MUL | NULL |    | 
| weight | tinyint(1) unsigned | NO |  | NULL |    | 
| source | varchar(8)   | YES |  | GEN  |    | 
+----------+---------------------+------+-----+---------+----------------+ 

這是我簡單的查詢:

SELECT 
    bagging.topic_id as topic_id, 
    topic.label as topic_label, 
    bagging.term_id as term_id, 
    term.label as term_label, 
    bagging.weight as weight, 
    bagging.source as source 
FROM 
    bagging 
JOIN term ON term.id = bagging.term_id 
JOIN topic ON topic.id = bagging.topic_id 
WHERE 
    bagging.topic_id = (SELECT id FROM topic WHERE label = 'Altruism') 
ORDER BY 
    bagging.weight DESC 

這給了我下面的結果:

+----------+-------------+---------+-----------------------+--------+--------+ 
| topic_id | topic_label | term_id | term_label   | weight | source | 
+----------+-------------+---------+-----------------------+--------+--------+ 
|  8 | Altruism |  83 | Altruism    | 100 | TOPIC | 
+----------+-------------+---------+-----------------------+--------+--------+ 
|  8 | Altruism |  100 | Altruism (philosophy) |  95 | WPRD | 
|  8 | Altruism |  100 | Altruism (philosophy) |  95 | MAN | 
|  8 | Altruism |  84 | Truist    |  95 | MAN | 
|  8 | Altruism |  84 | Truist    |  15 | WPRD | 
+----------+-------------+---------+-----------------------+--------+--------+ 
|  8 | Altruism |  94 | Selfless action  |  95 | WPRD | 
|  8 | Altruism |  95 | Alturism    |  95 | WPRD | 
|  8 | Altruism |  96 | Digital altruism  |  95 | WPRD | 
|  8 | Altruism |  97 | Selflessly   |  95 | WPRD | 
|  8 | Altruism |  98 | Altruistical   |  95 | WPRD | 
|  8 | Altruism |  99 | Law of mutual aid  |  95 | WPRD | 
|  8 | Altruism |  101 | Altruistically  |  95 | WPRD | 
|  8 | Altruism |  85 | Altruistic   |  95 | WPRD | 
|  8 | Altruism |  86 | Altruist    |  95 | WPRD | 
|  8 | Altruism |  87 | Otherism    |  95 | WPRD | 
|  8 | Altruism |  88 | Unselfishness   |  95 | WPRD | 
|  8 | Altruism |  89 | Altruistic behavior |  95 | WPRD | 
|  8 | Altruism |  90 | Altutrists   |  95 | WPRD | 
|  8 | Altruism |  91 | Altruists    |  95 | WPRD | 
|  8 | Altruism |  102 | Pathological altruism |  95 | WPRD | 
+----------+-------------+---------+-----------------------+--------+--------+ 

現在,如何創建一個計分功能,將採取以下考慮到這個特定的例子:

  • Altruism是無與倫比的,只能等於(= 100)
  • Truist顯然應該由15/100重量,但這樣的事實,有兩個也應被考慮,尤其是,因爲第二是95
  • 受到懲罰Altruist (Philosophy)體重應該超過所有其他(除Altruism不是隻能望其項背。)即使95倍看起來大於100

最終的結果並沒有從1擴展到100,它可以是考慮到這些限制的相對或抽象評級。

我試着通過計算每行(term_sum_weight * 100/topic_weight_sum_of_all_terms),但看到下面的結果,它們沒有足夠的重量。

Results computed on spreadsheets to try. 例如,我如何給95至96,比1至20更多的權重?

該公式比在將要使用的語言更重要...... MySQL或Python/PHP中的程序。

預期結果(沿着這些線路...)

+----------+-------------+---------+-----------------------+-------+--------+ 
| topic_id | topic_label | term_id | term_label   | score | source | 
+----------+-------------+---------+-----------------------+-------+--------+ 
|  8 | Altruism |  83 | Altruism    |  1 | TOPIC | 
+----------+-------------+---------+-----------------------+-------+--------+ 
|  8 | Altruism |  100 | Altruism (philosophy) | 0.98 | WPRD | 
|  8 | Altruism |  84 | Truist    | 0.96 | MAN | 
+----------+-------------+---------+-----------------------+--------+-------+ 
|  8 | Altruism |  94 | Selfless action  | 0.95 | MAN | 
|  8 | Altruism |  95 | Alturism    | 0.95 | MAN | 
|  8 | Altruism |  96 | Digital altruism  | 0.95 | MAN | 
           ........... 
|  8 | Altruism |  97 | Selflessly   | 0.95 | MAN | 
|  8 | Altruism |  90 | Altutrists   | 0.95 | MAN | 
|  8 | Altruism |  91 | Altruists    | 0.95 | MAN | 
|  8 | Altruism |  102 | Pathological altruism | 0.95 | MAN | 
+----------+-------------+---------+-----------------------+--------+-------+ 
+1

您的預期成果是什麼? – Viki888

+1

請參閱http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple-sql-查詢 – Strawberry

+0

1.您對您想要的內容(項目符號列表和引見)的描述無法理解。 2.粗略地說,猜測,您的評分函數可能應該包括將給定對的權重總和除以該對的行數。 – philipxy

回答

1

您應該制定一些屬性你想要的公式應該開始。一些可能的假設可能是以下幾點:

  1. 重量100結果總是在最大比分的裝袋(無論是1或100)
  2. 添加裝袋體重零改變不了什麼
  3. 添加了套袋非零權重增加了對分數,除非得分已經處於最大
  4. 如果兩個對具有單個裝袋每個,然後更大的重量導致更大的得分

條件2和3建議像增加一樣。但條件1告訴你,你不能只是添加,因爲這樣做會超過分數。一種觀察這種方式的方法是使用物理模擬器。把你的體重看成是速度。在日常生活中,您可以簡單地增加速度。但在非常高的速度下,狹義相對論告訴我們,我們永遠不能超過光速的極限。增加低於光速的兩種速度會導致更高的速度,但仍低於光速。在你的設置中,「光速」是100的最大值。

因此,查找the formula for the addition of speeds並將其調整爲您的使用案例。如果你有兩個重量baggings v瓦特那麼總重量達到

(v + w)/(1 + v*w/10000) 

現在你需要或者制定出一個公式,做了一個公式中加數的任意數以上,或者編寫一些應用程序代碼來逐步計算累加器與數據庫中下一項之間的總和。或者你在維基百科閱讀和發現下列公式成立:

c-s c-v c-w 
--- = --- * --- 
c+s c+v c+w 

這裏小號是速度的總和,或在你的世界了比分。但是更大的變化,這個部分將變得越小。因此,而不是由小號在按降序排序,你可以按照(ç - 小號)按升序/(ç + 小號)。不幸的是MySQL doesn't have a PRODUCT aggregate function。但是你可以用對數把產品打入款項:

SUM(LOG((100-weight)/(100+weight))) AS score 

不幸的是,MySQL不會處理無窮的方式IEEE浮點運算呢(即數(0)=-∞),但原來的重量100得分爲NULL。因此,您可以使用SORT BY (score IS NULL) DESC或其他類似方法將NULL分數排序在非NULL之前。或者你可以用正確處理零的方式將上面的內容轉換回值s

SELECT …, 
    IF(MAX(weight) = 100, 1, 
    (1-EXP(SUM(LOG((100-weight)/(100+weight)))))/ 
    (1+EXP(SUM(LOG((100-weight)/(100+weight)))))) AS score 

在這裏,你能想到的EXP(SUM(LOG(…)))作爲PRODUCT(…)的。要解決(c-s)/(c+s)=ps(以及p作爲我剛纔提到的產品),您需要計算s=c*(1-p)/(1+p)。因此,通過忽略c*,您可以獲得0到1之間的分數,而不是0到100分,與您迄今在計算中所做的相似。 MAX(weight) = 100的情況是什麼會導致LOG(0)使整個計算NULL,因此必須分開處理。

有關使用您的數據的示例,請參閱http://sqlfiddle.com/#!9/1cd56/1。它爲利他主義返回1,爲利他主義(哲學)爲0.9987,爲Truism返回0.9628,其他爲0.95。第二個分數比你在問題中預期的要大得多,但我沒有一個好主意來調整公式,使其更像你所期望的。

+0

它確實給了我正確的答案,並且我嘗試了各種各樣的情景,這些情景都是積極的。它完美地處理重量或障礙。現在,坦率地說,如果你的解釋不是很清楚,但我在香港已經遲到了,所以明天早上我會徹底解決它。感謝您花時間... – Lazhar