我正在为一个有预备会议室的地方创建数据库。卖书。该模式是通用的,允许重用多个数据集的表。
该图略有不正确;有两个selector
表实际上有不同的名称。右上角的selector
表实际上称为option_selector
,左下角是values_selector
。我用resource_type
填充1, room
表格; 2, book
然后resource_option
与1, Name
; 2, size
; 3,Author
; 4,Publish Year
并在option_selector
表格中填入行。
1, 1, 1
用于将房间映射到名称2, 1, 2
用于将房间映射到大小3, 2, 1
用于将图书映射到名称4, 2, 3
用于将图书映射到作者5, 2, 4
用于将图书映射到发布年份我还在option_selector
和option_value
表中添加了一些行。然后我运行这个查询
SELECT r.id as 'book ID', v.value as 'Name'
FROM resources r
JOIN value_selector s ON r.id = s.resource_id
JOIN resourse_option_value v ON s.value_id = v.id
WHERE v.option_selector_id = 3
ORDER BY r.id
结果
book ID Name
5 Journey to the center of the Earth
6 Oliver Travels
7 C How To Program
8 Java How To Program
这是正确的输出。
问题是我想添加更多数据列,以便可以通过书籍记录进行选择,例如“作者”和“作者”。 '发布年'使此输出表看起来像
book ID Name Author Publish Year
我试过这个
SELECT r.id as 'book ID', v.value as 'Name', v2.value as 'Author', v3.value as 'Year'
FROM resourses r
JOIN value_selector s ON r.id = s.resourse_id
JOIN resourse_option_value v ON s.value_id = v.id
JOIN resourse_option_value v2 ON s.value_id = v2.id
JOIN resourse_option_value v3 ON s.value_id = v3.id
WHERE
v.option_selector_id = 3 AND
v2.option_selector_id = 4 AND
v3.option_selector_id = 5
ORDER BY r.id
这给出了一个空结果
答案 0 :(得分:1)
我的数据库结构仍然不清楚。
但是只是为了让你知道从哪里开始你可以试试这个:
SELECT
r.id as 'book ID',
MAX(IF(v.option_selector_id = 3,v.value, null)) as 'Name',
MAX(IF(v.option_selector_id = 4,v.value, null)) as 'Author',
MAX(IF(v.option_selector_id = 5,v.value, null)) as 'Publish year'
FROM resourses r
JOIN value_selector s
ON r.id = s.resourse_id
JOIN resourse_option_value v
ON s.value_id = v.id
GROUP BY r.id
ORDER BY r.id
我觉得这个查询不会带来预期的结果,因为它是值依赖查询,我不知道什么是正确的值。因此,如果您提供更多数据样本,我们可以确定您的案例中的正确查询。请提供所有表格的样本和/或sqlfiddle是完美的。
编辑1 因此,如果您只需要图书,只需添加WHERE r.type_id = 2
子句:
http://sqlfiddle.com/#!9/302671/12
SELECT
r.id as 'book ID',
MAX(IF(v.option_selector_id = 3,v.value, null)) as 'Name',
MAX(IF(v.option_selector_id = 4,v.value, null)) as 'Author',
MAX(IF(v.option_selector_id = 5,v.value, null)) as 'Publish year'
FROM resourses r
JOIN value_selector s
ON r.id = s.resourse_id
JOIN resourse_option_value v
ON s.value_id = v.id
WHERE r.type_id = 2
GROUP BY r.id
ORDER BY r.id
编辑2 要获得特定年份的图书,您可以:
http://sqlfiddle.com/#!9/302671/15
SELECT
r.id as 'book ID',
MAX(IF(v.option_selector_id = 3,v.value, null)) as 'Name',
MAX(IF(v.option_selector_id = 4,v.value, null)) as 'Author',
MAX(IF(v.option_selector_id = 5,v.value, null)) as 'Publish year'
FROM resourses r
JOIN value_selector s
ON r.id = s.resourse_id
JOIN resourse_option_value v
ON s.value_id = v.id
WHERE r.type_id = 2
GROUP BY r.id
HAVING `Publish year`=2014
ORDER BY r.id
答案 1 :(得分:0)
嗯,Alex的回答表明该架构是可行的。在我看来,它仍然非常疯狂。特别是,在简单的查找语句中需要MAX
和HAVING
子句对可伸缩性非常关注。为了进行比较,请考虑使用Jay提出的单独表格的模式。
CREATE TABLE `book` (
`bookId` INT NOT NULL AUTO_INCREMENT,
`title` VARCHAR(45) NOT NULL,
`author` VARCHAR(45) NOT NULL,
`publishYear` INT NOT NULL,
PRIMARY KEY (`bookId`));
INSERT INTO `book` (`title`, `author`, `publishDate`) VALUES
("Journey to the center of the Earth", "Johny", 2013),
("Oliver Travels", "Ahmed Ali", 2015);
CREATE TABLE `room` (
`roomId` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NOT NULL
PRIMARY KEY (`roomId`));
INSERT INTO `room` (`name`) VALUES
("Library"), ("Study"), ("Hall"), ("Dining Room"), ("Kitchen"), ("Conservatory"), ("Billiard Room"), ("Lounge"), ("Ballroom");
你已经完成了。没有空(这不是MySQL中的一个大问题,实际上是reduce storage requirements on the InnoDB engine),没有外键,只有一半的SQL可以将它拉下来。您可以通过其表名和ID轻松地告诉任何数据记录是什么,而无需为列名,选项名称和值检查三个不同的表。
需要书籍吗?
SELECT `bookId`, `title`, `author`, `publishYear` FROM `book`;
从某一年开始? (可能希望在发布年份添加索引。)
SELECT `bookId`, `title`, `author`, `publishYear` FROM `book`
WHERE `publishYear` = 2013;
需要让书籍有多位作者吗?
CREATE TABLE `author` (
`authorId` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45),
`bookId` INT NOT NULL,
PRIMARY KEY(`authorId`));
ALTER TABLE `book` DROP COLUMN `author`;
SELECT `b`.`bookId`, `title`, GROUP_CONCAT(`name`) as authors, `publishYear`
FROM `book` b
LEFT JOIN `author` a ON `a`.`bookId` = `b`.`bookId`
GROUP BY `b`.`bookId`;
如果您愿意,请添加外键。