来自不同表的许多列的 where 子句的语法是什么?
What is the syntax for a where clause for many columns from different tables?
我正在为一个有会议室的地方创建数据库,用于预订和销售书籍。该模式被通用化以允许对多个数据集重复使用 table。
图表略有不正确;有两个 selector
table 实际上有不同的名字。右上角的selector
table其实叫option_selector
,左下角的values_selector
。我用 1, room
填充 resource_type
table; 2, book
然后 resource_option
和 1, Name
; 2, size
; 3,Author
; 4,Publish Year
并用行填充 option_selector
table。
1, 1, 1
用于映射房间名称
2, 1, 2
用于将空间映射到大小
3, 2, 1
映射书名
4, 2, 3
用于将书映射到作者
5, 2, 4
将图书映射到出版年份
我还用一些行填充了 option_selector
和 option_value
table。然后我运行这个查询
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
这是正确的输出。
问题是我想添加更多数据列来选择 table 与书籍记录,例如 'Author' & 'Publish Year' 使这个输出 table 看起来喜欢
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
这给出了一个空结果
数据库 sql : http://sqlfiddle.com/#!9/302671/3
我还不清楚你的数据库结构。
但只是为了让您知道从哪里开始,您可以试试这个:
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
我觉得这个查询不会给你带来预期的结果,因为它是依赖于值的查询,我不知道什么是正确的值。因此,如果您提供更多数据样本,我们可以找出您的案例中的正确查询。请提供所有表的示例 and/or 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
好吧,Alex 的回答表明该架构是可行的。在我看来,这仍然很疯狂。特别是,在应该是简单查找语句的地方需要 MAX
和 HAVING
子句对于可伸缩性来说非常重要。为了进行比较,请考虑 Jay 提出的具有单独 table 的模式。
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 的一半才能实现。您可以通过其 table 名称和 ID 轻松判断任何数据记录是什么,而无需检查三个不同的 table 列名称、选项名称和值。
需要这些书吗?
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`;
如果您愿意,可以添加外键。
我正在为一个有会议室的地方创建数据库,用于预订和销售书籍。该模式被通用化以允许对多个数据集重复使用 table。
图表略有不正确;有两个 selector
table 实际上有不同的名字。右上角的selector
table其实叫option_selector
,左下角的values_selector
。我用 1, room
填充 resource_type
table; 2, book
然后 resource_option
和 1, Name
; 2, size
; 3,Author
; 4,Publish Year
并用行填充 option_selector
table。
1, 1, 1
用于映射房间名称2, 1, 2
用于将空间映射到大小3, 2, 1
映射书名4, 2, 3
用于将书映射到作者5, 2, 4
将图书映射到出版年份
我还用一些行填充了 option_selector
和 option_value
table。然后我运行这个查询
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
这是正确的输出。
问题是我想添加更多数据列来选择 table 与书籍记录,例如 'Author' & 'Publish Year' 使这个输出 table 看起来喜欢
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
这给出了一个空结果
数据库 sql : http://sqlfiddle.com/#!9/302671/3
我还不清楚你的数据库结构。
但只是为了让您知道从哪里开始,您可以试试这个:
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
我觉得这个查询不会给你带来预期的结果,因为它是依赖于值的查询,我不知道什么是正确的值。因此,如果您提供更多数据样本,我们可以找出您的案例中的正确查询。请提供所有表的示例 and/or 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
好吧,Alex 的回答表明该架构是可行的。在我看来,这仍然很疯狂。特别是,在应该是简单查找语句的地方需要 MAX
和 HAVING
子句对于可伸缩性来说非常重要。为了进行比较,请考虑 Jay 提出的具有单独 table 的模式。
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 的一半才能实现。您可以通过其 table 名称和 ID 轻松判断任何数据记录是什么,而无需检查三个不同的 table 列名称、选项名称和值。
需要这些书吗?
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`;
如果您愿意,可以添加外键。