MySQL图片和类别之间的多重关系

时间:2014-10-30 02:07:12

标签: mysql sql database relational-database

我目前正在努力在MySQL中创建一个具有多个连接和条件的适当查询。我已经找到了一个类似的问题(https://stackoverflow.com/questions/5016257/mysql-select-where-in-but-not-in-with-join),它引导我在帖子的底部进行查询。但是这不能正常工作。

查看数据库模式的SQLFiddle:http://sqlfiddle.com/#!9/4ab0e/2。 (我不知道如何制作这些很好的文本格式)

当前数据库架构:

sketch_category

categoryID  int(10)
name    varchar(245)    
rank    tinyint(4)
grouped tinyint(4)

sketch_picture

picture_id  bigint(20)
picture_name    varchar(45) N
picture_url varchar(125)

sketch_tag

tag_id(20)
tag_name bigint(20)
rank int(11)

sketch_picture_category

picture_id  bigint(20)
category_id int(11)

sketch_picture_tag

picture_id  bigint(20)
tag_id bigint(20)

sketch_picture_category负责sketch_picturesketch_category之间的关系,因此sketch_picture_tag负责sketch_picturesketch_tag的关系

我遇到了几个问题: 包含OR语句的简单查询工作正常。但是如上所述,任何其他AND声明都不会给我任何结果。

可能的查询可能是: 我们假设我想查找类别:

  • 希望所有照片都属于该类别"女性" AND"男性"和"穿上" (但不是所有其他人)
  • 希望所有照片都属于该类别"女性" AND"男性"和"穿上"和"裸体" (但不是所有其他人)
  • 希望将所有照片归入类别" stillifee" (但不是所有其他人)

到目前为止,我在这里使用了这个查询,但它并没有完全适用于所有查询。它只有在我同时拥有不同的类别时才有效 - 所以"女性和男性"但添加"穿着和裸体"不再工作了。

QUERY:

SELECT * FROM sketch_picture p
JOIN sketch_picture_category pc1 ON p.picture_id = pc1.picture_id and pc1.category_id = 1
JOIN sketch_picture_category pc2 ON p.picture_id = pc2.picture_id and pc2.category_id = 4
JOIN sketch_category c1 ON pc1.category_id = c1.categoryID
JOIN sketch_category c2 ON pc2.category_id = c2.categoryID
LEFT JOIN sketch_picture_tag pt1 ON p.picture_id = pt1.pictures_id
LEFT JOIN sketch_picture_tag pt2 ON p.picture_id = pt2.pictures_id
WHERE pt1.tag_id IN (1, 2, 3, 5, 6) AND pt2.tag_id IN (1, 2, 3, 5, 6) OR pt1.tag_id IS NULL OR 
pt2.tag_id IS NULL
GROUP BY p.picture_id

结果:

+------------+--------------+-----------------------------------------+------------+-------------+------------+-------------+------------+--------+------+---------+------------+------+------+---------+-------------+--------+-------------+--------+
| picture_id | picture_name | picture_url                             | picture_id | category_id | picture_id | category_id | categoryID | name   | rank | grouped | categoryID | name | rank | grouped | pictures_id | tag_id | pictures_id | tag_id |
| 1          | Nude Women   | Art_Nudes___C_11_by_mjranum_stock.jpg   | 1          | 1           | 1          | 4           | 1          | female | 1    | 0       | 4          | nude | 2    | 0       | NULL        | NULL   | NULL        | NULL   |
| 2          | Nude Women 2 | Art_Nudes___C_16_by_mjranum_stock_1.jpg | 2          | 1           | 2          | 4           | 1          | female | 1    | 0       | 4          | nude | 2    | 0       | NULL        | NULL   | NULL        | NULL   |
| 5          | nude women   | The_Dive_by_mjranum_stock.jpg           | 5          | 1           | 5          | 4           | 1          | female | 1    | 0       | 4          | nude | 2    | 0       | NULL        | NULL   | NULL        | NULL   |
+------------+--------------+-----------------------------------------+------------+-------------+------------+-------------+------------+--------+------+---------+------------+------+------+---------+-------------+--------+-------------+--------+

然而,提到的unworking查询没有结果:

SELECT * FROM sketch_picture p
JOIN sketch_picture_category pc1 ON p.picture_id = pc1.picture_id and pc1.category_id = 1 and pc1.category_id = 2
JOIN sketch_picture_category pc2 ON p.picture_id = pc2.picture_id and pc2.category_id = 3 and pc2.category_id = 4
JOIN sketch_category c1 ON pc1.category_id = c1.categoryID
JOIN sketch_category c2 ON pc2.category_id = c2.categoryID
LEFT JOIN sketch_picture_tag pt1 ON p.picture_id = pt1.pictures_id
LEFT JOIN sketch_picture_tag pt2 ON p.picture_id = pt2.pictures_id
WHERE pt1.tag_id IN (1, 2, 3, 5, 6) AND pt2.tag_id IN (1, 2, 3, 5, 6) OR pt1.tag_id IS NULL OR 
pt2.tag_id IS NULL
GROUP BY p.picture_id

假设的结果应显示在category 1 (female) AND 2 (male)内的所有图片中,其中category 3 (clothed) and 4 (nude)

我尝试的另一种方式是:

SELECT * FROM sketch_picture p
inner join sketch_picture_category pc on(p.picture_id = pc.picture_id )
inner join sketch_category c on (c.categoryID = pc.category_id) 
WHERE pc.category_id = 1 OR pc.category_id = 3
GROUP BY p.picture_id

产生这些错误的结果 - 我只需要1类和3类(女性和衣服)的照片。然而,这会产生每个女性和每件衣服的照片:

+------------+-------------------------+--------------------------------------------------+------------+-------------+------------+---------+------+---------+
| picture_id | picture_name            | picture_url                                      | picture_id | category_id | categoryID | name    | rank | grouped |
| 1          | Nude Women              | Art_Nudes___C_11_by_mjranum_stock.jpg            | 1          | 1           | 1          | female  | 1    | 0       |
| 2          | Nude Women 2            | Art_Nudes___C_16_by_mjranum_stock_1.jpg          | 2          | 1           | 1          | female  | 1    | 0       |
| 3          | clothed man             | fly___3_by_mjranum_stock-d48bpkr.jpg             | 3          | 3           | 3          | clothed | 2    | 0       |
| 4          | clothed_women           | mervilina_by_mervilina-d6n71qa.jpg               | 4          | 1           | 1          | female  | 1    | 0       |
| 5          | nude women              | The_Dive_by_mjranum_stock.jpg                    | 5          | 1           | 1          | female  | 1    | 0       |
| 20         | abrham lincoln          | Abraham_Lincoln_head_on_shoulders_photo_portrait | 20         | 3           | 3          | clothed | 2    | 0       |
| 21         | women female head       | Vicki-Head-4.jpg                                 | 21         | 1           | 1          | female  | 1    | 0       |
| 22         | head-in-hands-sculpture | head-in-hands-sculpture.jpg                      | 22         | 3           | 3          | clothed | 2    | 0       |
| 23         | old women               | 8763_10105_combobw_mix2.jpg                      | 23         | 1           | 1          | female  | 1    | 0       |
+------------+-------------------------+--------------------------------------------------+------------+-------------+------------+---------+------+---------+

如果我将声明更改为" OR"到" AND"它将产生0结果

SQLFiddle:http://sqlfiddle.com/#!9/4ab0e/2

1 个答案:

答案 0 :(得分:0)

我真的不明白你的数据,但我的想法是:

你将在前端的某个地方提供类似多种属性的选择,你需要一种方法来找到那些具有所有这些属性但没有其他属性的图片,而且相当简单。

这个估计是否正确?

假设这是正确的,那么,相当简单的部分可能不那么容易,但我的想法是你需要做这样的事情:(这不是mysql,我不知道mysql的语法,你'我需要翻译)

select category_id into temporary_category_table from sketch_category
where Category in ('male', 'female', ...) --selections applicable

获取所有图片,将temporary_category_table中的任何category_id放入另一个表格中,我将其称为all_possible_data。此数据需要包含picture_id和每个picture_id存在的每个category_id。你可能比我更好地写这篇文章,因为我不清楚这些数据。 All_possible_data将包含不同的picture_id - category_id组合。

使用此表,您需要一种动态查找all_possible_data中出现在temporary_category_table中的所有category_ids的图片的方法。

由于需要支持无限数量的类别,这并不是很简单。

我的感觉是,最简单的方法是使用循环逐步消耗放入temporary_category_table的数据,以编程方式构建提供数据的sql语句,如下所示:

select @attrib_no = 1

select @category_id = min(category_id) from temporary_category_table
delete temporary_category_table where category_id = @category_id

select @sql = "SELECT a.picture_id INTO temporary_result_table FROM ("
select @sql = "SELECT DISTINCT picture_id FROM all_possible_data WHERE category_id = "
select @sql = @sql + str(@category_id) + ") a"

while (select count(*) from temporary_category_table) > 0 begin
    select @category_id = min(category_id) from temporary_category_table
    delete temporary_category_table where category_id = @category_id
    select @sql = @sql + " INNER JOIN (SELECT picture_id FROM all_possible_data" 
    select @sql = @sql + " WHERE category_id = " + str(@category_id) + ") a"
    select @sql = @sql + str(@attrib_no) + " on a.picture_id = a" + str(@attrib_no) + ".picture_id"
    select @attrib_no = @attrib_no + 1
end

然后运行@sql将创建temporary_result_table,其中包含具有所有选定类别的picture_ids,但不包含任何没有或只有部分类别的图片。

此逻辑不考虑任何其他类别不在picture_ids选项中的类别。

希望这会有所帮助,或至少给你一些想法。