2010-12-03 70 views
0

我在这里遇到了一些难题。我正在烘烤食谱应用程序,并假设我有“蛋黄酱”,“培根”和“奶酪”的查询。MySQL获取UNION,按交叉点排序?

我想返回所有包含“蛋黄酱”或“培根”或“奶酪”的食谱,如果他们有“蛋黄酱”,“培根”和“奶酪”,然后是那些只有“蛋黄酱”和“腊肉”等

到目前为止,我有东西有点cloogey喜欢:

SELECT * FROM recipes 
    WHERE LOWER(ingredients) LIKE '%mayonnaise%' 
    OR LOWER(ingredients) LIKE '%bacon%' 

但是,这只是其中的一个我想要的一半。我如何才能通过终点线?

谢谢!

+0

我相信你已经意识到了这一点,但是你的数据库设计并不理想......规范化可以使它执行得更好,并且使编写这些类型的查询变得更容易。 – 2010-12-03 07:16:19

回答

1

你可以尝试优先成分的存在和顺序由成分是否被包括:

SELECT * FROM recipes 
WHERE LOWER(ingredients) LIKE '%mayonnaise%' 
OR LOWER(ingredients) LIKE '%bacon%' 
OR LOWER(ingredients) LIKE '%cheese%' 
ORDER BY LOWER(ingredients) LIKE '%mayonnaise%' DESC, 
     LOWER(ingredients) LIKE '%bacon%' DESC, 
     LOWER(ingredients) LIKE '%cheese%' DESC 
+0

这工作得很好!谢谢! – Rio 2010-12-03 08:48:48

0

我不知道,如果食谱有一个主键,但我会承担它。我们给每个单词1分。

SELECT r.* FROM recipes 
LEFT JOIN recipes m ON r.id = m.id AND LOWER(m.ingredients) LIKE '%mayonnaise%' 
LEFT JOIN recipes b ON r.id = b.id AND LOWER(b.ingredients) LIKE '%bacon%' 
LEFT JOIN recipes c ON r.id = c.id AND LOWER(c.ingredients) LIKE '%cheese%' 
ORDER BY 
(CASE WHEN m.id IS NULL THEN 0 ELSE 1 END)+ 
(CASE WHEN b.id IS NULL THEN 0 ELSE 1 END)+ 
(CASE WHEN c.id IS NULL THEN 0 ELSE 1 END) DESC 
+0

这是一个不错的解决方案,但它花费大约8秒钟运行12,000条记录。我意识到这是对数据结构的反思,但是谢谢! – Rio 2010-12-03 08:49:21

+0

@Rio同意,这肯定没有效率。很高兴你找到适合你的目的的东西! – 2010-12-03 08:51:49

0

如果可能的话(和你似乎正在建造新的东西),也许你应该重新考虑你的表格布局。看起来你有一列中的成分,可能是用逗号分隔的东西。这实际上不能很好地扩展,甚至可以做出简单的查询,比如您想要的复杂和缓慢的查询(在实际搜索术语前面使用所有这些通配符会有效地禁用任何索引使用)。

也许为INGREDIENTS建立一个单独的表格,建议将n:m基数与RECIPES表格的关系。

伪SQL:

CREATE TABLE RECIPES (id int not null, [...more columns...]) PRIMARY KEY id; 
CREATE TABLE INGREDIENTS (id int not null, name varchar(30), [...more columns...]) PRIMARY KEY id; 
CREATE TABLE RECIPE_INGREDIENTS (recp_id int not null, ingred_id not null); 

这样,你可以加入配方和成分:

SELECT RECIPES.id AS recipe, COUNT(INGREDIENTS.id) AS matching_ingredients 
    FROM RECIPES r JOIN RECIPE_INGREDIENTS ri ON r.ID=ri.recp_id 
        JOIN INGREDIENTS i ON ri.ingred_id = i.id 
    WHERE INGREDIENTS.name in ('mayonnaise', 'bacon', 'cheese') 
GROUP BY COUNT(INGREDIENTS.id) 

通往配方数量的表格及配套原料的数量。这也会从索引中受益。

请注意,我现在手边没有MySQL服务器,所以上面的内容是写在我头上的。也许我的语法错了一点。此外,您可能想要添加外键信息,但这并不是必需的,才能使其运行。

请参阅MySQL手册中的CREATE TABLE语法。