2012-10-31 182 views
2

我希望這個問題不是多餘的。我試圖完成的是讓用戶在頁面上選擇一堆複選框,並在沒有匹配的行時返回最接近的匹配記錄。例如:返回SQL查詢結果,即使找不到精確匹配

一個人檢查過[X]蘋果[X]橙子[X]梨[X]香蕉

但表看起來像這樣:

Apples  Oranges  Pears  Bananas 
1    1   1  null 
1    1   null  1 
1    1   null  null 

(顯然我錯過了id列),所以我們希望得到的結果是讓這三行仍然按大多數匹配的順序返回,所以它們現在的順序幾乎是一樣的。我只是不確定採取這種方式的最佳方法。我已經考慮過全文搜索,即levenshtein函數,但我真的很想回到完全匹配的想法,如果它存在。如果不需要,不需要用代碼詳細說明。我只是希望能夠朝着正確的方向發展。我看過其他類似的問題,但我仍然不確定要走哪條路。

謝謝!

+0

不知道我是否理解正確,但如果我這樣做只是''ORDER BY orances DESC,pears DESC,bananas DESC'' – Tim

+0

該表可以在這些列中包含1或NULL以外的值嗎?如果一場比賽被認爲是積極的,那麼一場不匹配會被認爲是否定的?你想將NULL視爲匹配所有內容還是不匹配?也許這意味着UNKNOWN,也許意味着MISSING? – MatBailie

+0

爲我的目的是空的有效0。我正在嘗試做一個二進制系統。如果該列已被標記,則爲1;如果該列尚未標記,則爲null。我的意圖是沒有空值喚起懷疑或沒有。 – user1789907

回答

2

編寫一個查詢,該查詢添加了匹配的列數,並按該總數對行進行排序。例如。

SELECT * 
FROM mytable 
ORDER BY COALESCE(Apples, 0) = $apples + COALESCE(Oranges, 0) = $oranges + ... DESC 
+0

巴爾瑪,甜心人!這像一個魅力。 – user1789907

0

這是相當簡單的,但你可以使用IFNULL()(MySQL的,或者你的數據庫的當量)返回匹配的總和和使用,在您的ORDER BY

// columns and weighting score 
$types = array("oranges"=>1, "apples"=>1, "bananas"=>1, "pears"=>1); 
$where = array(); 
// loop through the columns 
foreach ($types as $key=>&$weight){ 
    // if there is a match in $_REQUEST at it to $where and increase the weight 
    if (isset($_REQUEST[$key])){ 
     $where[] = $key . " = 1"; 
     $weight = 2; 
    } 
} 
// build the WHERE clause 
$where_str = (count($where)>0)? "WHERE " . implode(" OR ", $where) : ""; 

// build the SQL - non-null matches from the WHERE will be weighted higher 
$sql = "SELECT apples, oranges, pears, bananas, "; 
foreach ($types as $key=>$weight){ 
    $sql .= "IFNULL({$key}, 0, {$weight}) + "; 
} 
$sql .= "0 AS score FROM `table` {$where_str} ORDER BY score DESC"; 

假設「橙子」和「蘋果」的選擇,你的SQL將是:

SELECT apples, oranges, pears, bananas, 
IFNULL(apples, 0, 2) + IFNULL(oranges, 0, 2) + IFNULL(pears, 0, 1) + IFNULL(bananas, 0, 1) + 0 AS score 
FROM `table` 
WHERE oranges = 1 OR apples = 1 
ORDER BY score DESC 
+0

這是如何使用複選框的輸入? – Barmar

+0

好的,甜的!我將深入研究這個問題,跟隨你們的領導者做一些研究。我會讓你知道我的公平。感謝您的及時回覆。讚賞。 – user1789907

+0

我打算通過php以某種方式傳遞變量,哈哈。 – user1789907

0

訂購複選框/數據的總和下降相匹配

SELECT * FROM table 
ORDER BY (COALESE(Apple,0) * @apple) + (COALESE(Orange,0) * @orange) ..... DESC 

其中@apple/@orange代表用戶選擇:1 =檢查,0 =選中

1

這很容易通過分數來排序...

SELECT fb.ID, fb.Apples, fb.Oranges, fb.Pears, fb.Bananas 
FROM FruitBasket fb 
ORDER BY 
    CASE WHEN @Apples = fb.Apples THEN 1 ELSE 0 END 
    + CASE WHEN @Oranges = fb.Oranges THEN 1 ELSE 0 END 
    + CASE WHEN @Pears = fb.Pears THEN 1 ELSE 0 END 
    + CASE WHEN @Bananas = fb.Bananas THEN 1 ELSE 0 END 
    DESC, ID 

然而,這導致表掃描(甚至與TOP)。最後一條記錄可能比迄今爲止找到的記錄匹配得更好,因此每條記錄都必須被讀取。


你可以考慮一個標籤系統,像this

Content --<ContentTag>-- Tag 

這將是質疑這種方式:

SELECT ContentID 
FROM ContentTag 
WHERE TagID in (334, 338, 342) 
GROUP BY ContentID 
ORDER BY COUNT(DISTINCT TagID) desc 

上ContentTag.TagId的指數將這個查詢使用。