2012-10-31 118 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的指数将这个查询使用。