基本上我有一个图像库。只是想创造一个学习的目的。现在,当他/她单击category时,将触发以下mysql查询以选择库:
从库中选择ID、name、gallery_thumb
category1=$category\u id或category2=$category\u id或
category3=$category_id ORDER BY id描述
这只是一个快速而糟糕的解决方案,我把它拼凑在一起。基本上我想一个画廊出现在许多类别。在这里,我这样做,因为我创建了一个画廊,我可以添加到三个或更少的类别,因此一个画廊可能出现在不同的目录。但这不是我想要的。
图库表:
创建表“gallery”(
`ID`int(11)非空自动递增,
`name`varchar(1000)字符集utf8 COLLATE utf8_unicode_ci不为空,
`description`varchar(1000)字符集utf8 COLLATE utf8_unicode_ci不为空,
`category1`varchar(500)字符集utf8 COLLATE utf8_unicode_ci不为空,
`类别2`varchar(500)字符集utf8 COLLATE utf8_unicode_ci不为空,
`类别3`varchar(500)字符集utf8 COLLATE utf8_unicode_ci不为空,
`web_link`varchar(3000)字符集utf8 COLLATE utf8_unicode_ci不为空,
`gallery_thumb`varchar(2000)字符集utf8 COLLATE utf8_unicode_ci不为空,
`reg_time`时间戳不为空默认当前时间戳,
主键(`ID`)
)
category2和category3将是不必要的,如果我得到了我想要的功能,它们将被删除。
标记表:
创建表“gallery_tags”(
`ID`int(11)非空自动递增,
`tag_name`varchar(100)字符集utf8 COLLATE utf8_unicode_ci不为空,
主键(`ID`)
)
标记和库参考表:
创建表“gallery_tag_reference”(
`ID`int(11)非空自动递增,
`库id`int(11)不为空,
`标记'int(100)不为空,
主键(`ID`)
)
我添加了一个标签功能。现在,当我创建一个库时,我可以向库中添加任意数量的标记。现在,画廊将只有一个主要类别和许多标签绑定到它。但我希望库也出现在其他类别中,基于我创建库时添加的标记。类别将有一个或多个预定义的标记。我现在要做的是,当访问者单击类别时,将选择相同的数据,而这之前只有查询过滤部分是不同的。
例子:
类别1将有标签:汽车、蓝色、闪亮
厨房1将有标签:蓝色,红色,快速。
gallery1不属于category1,但因为它在“gallery_tags”表中添加了一个“blue”标记,所以它出现在访问者单击category1按钮时执行的查询结果中。
例2:
类别1将没有标记。
类别2将没有标记。
类别3将没有标记。
类别4将具有预定义的标记:黄色、红色。
类别5将具有预定义的标记:高、高。
Gallery1没有标签,但它属于Category1。
Gallery2没有标签,但它属于类别2。
Gallery3将有标签:黄色、高、地
厨房3属于类别3。
当访问者单击Category4按钮时,选择的是属于Category4的库和带有“黄色”或“红色”标记的库。因为在这里我们没有属于类别4的库,但是我们有带有黄色标记的gallery3,并且类别4也有预定义的标记“黄色”gallery3在单击时显示在类别4中。
类别5也是如此。它没有直接属于它的任何画廊,但因为gallery3有一个标记“高”绑定到它,Category5也有预定义的标记“高”,gallery3也显示在Category5中。
我希望我清楚地描述了我想要实现的目标。由于我在MySQL方面经验不多,所以在组合必要的查询时遇到了困难。我希望有人能帮忙!

最佳答案

好的,你的基本选择单位是标签和分类-让我们从为它们创建表开始

CREATE TABLE tags (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100) NOT NULL,
  -- Maybe some other things you want? Tag description?
  UNIQUE INDEX name
);

这给了我们一个tags表,我们可以用
INSERT INTO tags(name) VALUES
  ('car'),('blue'),('shiny'),('red'),('fast'),('yellow'),('tall'),('high'),('field')
;

基本上相同的事情发生在类别上:
CREATE TABLE categories (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100) NOT NULL,
  -- Maybe some other things you want? Description?
  UNIQUE INDEX name
);

INSERT INTO categories(name) VALUES
  ('cars'),('people'),('colors'),('landscapes'),('misc')
;

现在我们可以看看画廊:
每一个画廊都应该属于一个类别(现在),每一个
类别可以有许多库。所以这是一个
类别的POV,因此我们需要在1:n侧有一个指针字段
关系,画廊。我在这里不使用外键
简明扼要,我们强烈建议您考虑使用它们。
每个库都可以有许多标记,每个标记都可以属于许多库,因此这是一个n:m关系,我们不需要直接在表中使用字段,但我们需要一个连接表。
每个类别都可以有许多标记,每个标记都可以属于许多类别-所以这是一样的
所以我们要:
CREATE TABLE galleries (
  id int(11) PRIMARY KEY AUTO_INCREMENT,
  name varchar(100)  NOT NULL,
  category` INT NOT NULL,
  -- the other fields you want: description, web_link, gallery_thumb,reg_time
  UNIQUE INDEX(name)
)

注意类别的数据类型n:它将链接到categories表的主键,也就是INT
我们可能不会忘记联接表:
CREATE TABLE galleries_tags (
  gallery INT,
  tag INT,
  PRIMARY KEY(tag, gallery),
  KEY(gallery)
);

CREATE TABLE categories_tags (
  category INT,
  tag INT,
  PRIMARY KEY(tag, category),
  KEY(category)
);

INT类型的tag字段会将这些联接表链接到INT表的id字段,而tags则会。gallery字段将链接到相应表的category字段。
我们再次用id查询填充表格。(懒得写出来)
现在你的数据已经在数据库中了,是时候再把它取出来了:
你的用例:用户点击一个类别,你想选择画廊,有
或者被归入这一类
或与此类别共享标记
这很容易,但需要稍加思考:
您的目标表是INSERT
对于按类别进行的选择,您有一个直接选择器:categories字段
要按标记进行选择,必须通过上面的联接表进行联接
对于组合选择,如果您不想错过仅类别选择,则需要category,但这将扼杀您的性能。所以你选择分开,然后LEFT JOIN结果
假设您的用户选择了类别4:
SELECT * FROM galleries WHERE category=4
UNION
SELECT categories.*
FROM galleries
INNER JOIN galleries_tags ON galleries.id=galleries_tags.gallery
INNER JOIN categories_tags ON categories_tags.tag=galleries_tags.tag
WHERE categories_tags.category=4

鲍勃是你叔叔。
这个查询做什么?第一部分很简单,第二部分选择那些画廊
贴上标签(UNION
哪些标签附加了类别(INNER JOIN galleries_tags ON ...
哪些类别具有INNER JOIN categories_tags ON ...4

10-04 11:27
查看更多