Select 在一个独特的 table 系统中加入
Select with joins in a unique table system
我正在尝试在 omekaS 数据库上构建 SQL 查询以提取具有特定标题和日期的书籍。
在本系统中,持有值的table称为value
,相关属性如下:
value
-id (pk)
-resource_id
-type (int)
-value
resource_Id
是通过db的标识符
值是一个字段;就像写于 1822 年(随机日期)的《白鲸》一书在 db 中看起来像这样。类型告诉我们它是什么(任意地,1
是标题,2
是出版年份)
Id
resource_id
type
value
1
1
1
Moby dick
2
1
2
1822
我需要获取某一年出版的具有特定名称的所有书籍
基本上
Select all the columns from value
Where value is a title and of type title
And value is in a set of years
And with all these having the same resource_id
我迷路了,我不知道该怎么做。
最好的方法是什么?
谢谢
如果需要检查更多类型,可以用AND EXISTS (SELECT 1 FROM ...WHERE type = 3 AND ...)
检查是否满足条件
我重新命名了 table 名称,使用相同名称的 cloumn 名称和 table 名称令人困惑。
CREATE TABLE books (
`Id` INTEGER,
`resource_id` INTEGER,
`type` INTEGER,
`value` VARCHAR(20)
);
INSERT INTO books
(`Id`, `resource_id`, `type`, `value`)
VALUES
('1', '1', '1', 'Moby Dick'),
('2', '1', '2', '1822');
SELECT `resource_id`, `value` FROM books
WHERE `type` = 1 AND `resource_id` IN (SELECT `resource_id` FROM books WHERE `type`= 2 AND `value` IN ('1822','1984'))
resource_id | value
----------: | :--------
1 | Moby Dick
db<>fiddle here
如果你想把它们排成一行
SELECT b1.`resource_id`, b1.`value` , b2.`value`
FROM books b1 INNER JOIN books b2 ON b1.`resource_id` = b2.`resource_id` and b2.`type`= 2
WHERE b1. `type` = 1 ANd b1.`resource_id` IN (SELECT `resource_id` FROM books WHERE `type`= 2 AND `value` IN ('1822','1984'))
resource_id | value | value
----------: | :-------- | :----
1 | Moby Dick | 1822
db<>fiddle here
应该是一个简单的self-join。一个 table 的 where 子句与第二个过滤条件中的第二个实例具有相同的 ID。
select
v1.resource_id,
v1.value Title,
v2.value YearPublished
from
Value v1
Join Value v2
on v2.type = 2
AND v2.value in ( 1822, 1835, 1912 )
AND v1.resource_id = v2.resource_id
where
v1.type = 1
v1.value = 'Moby Dick'
我会在您的 table 上(类型,值,resource_id)创建一个复合索引,而不是在每一列上创建单独的索引
现在让我们看看它在做什么。如果您查看查询的非常基本的部分,因为它只与“v1”别名有关,它正在寻找类型 = 1(代表标题),并且值是感兴趣的书的名称。你可能很容易就明白了。
所以现在您所做的就是为一年 written/published 添加一个额外的标准(或您的其他“类型”数据表明的任何内容)。这将再次连接到相同的 table,但别名不同。现在,对于关系,只需将那个标准放在那里,但除此之外,您还要确保 resource_id 与找到的第一个 v1 资源相同。
这里的好处是,您的外部主要查询将开始首先查找符合标题条件的数据,这将是一个有点小的列表。然后,只有从那个小列表中,它甚至关心是否存在由同一资源和您正在查找的附加查询(日期、年份或其他内容的列表)连接到第二个 table 的条件。
现在,如果您有其他类型为 3 的“值”,但不关心其中的值是什么,您只需再次加入值 table 作为 ex:别名 v3,但是只加入 v3.type = 3 and v1.resource_id = v3.resource_id
通过使用别名引用和值列,只需将最终列别名分配给它应该代表的内容,如此处所示。
如果对相同的值 table 执行第 3 次、第 4 次或更多次这样的操作,您可能需要在 (resource_id、类型、值) 上添加一个索引。是的,两个索引具有相同的列,但为了优化第 2、3、4 个 JOIN 条件目的。
我正在尝试在 omekaS 数据库上构建 SQL 查询以提取具有特定标题和日期的书籍。
在本系统中,持有值的table称为value
,相关属性如下:
value
-id (pk)
-resource_id
-type (int)
-value
resource_Id
是通过db的标识符
值是一个字段;就像写于 1822 年(随机日期)的《白鲸》一书在 db 中看起来像这样。类型告诉我们它是什么(任意地,1
是标题,2
是出版年份)
Id | resource_id | type | value |
---|---|---|---|
1 | 1 | 1 | Moby dick |
2 | 1 | 2 | 1822 |
我需要获取某一年出版的具有特定名称的所有书籍
基本上
Select all the columns from value
Where value is a title and of type title
And value is in a set of years
And with all these having the same resource_id
我迷路了,我不知道该怎么做。
最好的方法是什么?
谢谢
如果需要检查更多类型,可以用AND EXISTS (SELECT 1 FROM ...WHERE type = 3 AND ...)
检查是否满足条件
我重新命名了 table 名称,使用相同名称的 cloumn 名称和 table 名称令人困惑。
CREATE TABLE books ( `Id` INTEGER, `resource_id` INTEGER, `type` INTEGER, `value` VARCHAR(20) ); INSERT INTO books (`Id`, `resource_id`, `type`, `value`) VALUES ('1', '1', '1', 'Moby Dick'), ('2', '1', '2', '1822');
SELECT `resource_id`, `value` FROM books WHERE `type` = 1 AND `resource_id` IN (SELECT `resource_id` FROM books WHERE `type`= 2 AND `value` IN ('1822','1984'))
resource_id | value ----------: | :-------- 1 | Moby Dick
db<>fiddle here
如果你想把它们排成一行
SELECT b1.`resource_id`, b1.`value` , b2.`value` FROM books b1 INNER JOIN books b2 ON b1.`resource_id` = b2.`resource_id` and b2.`type`= 2 WHERE b1. `type` = 1 ANd b1.`resource_id` IN (SELECT `resource_id` FROM books WHERE `type`= 2 AND `value` IN ('1822','1984'))
resource_id | value | value ----------: | :-------- | :---- 1 | Moby Dick | 1822
db<>fiddle here
应该是一个简单的self-join。一个 table 的 where 子句与第二个过滤条件中的第二个实例具有相同的 ID。
select
v1.resource_id,
v1.value Title,
v2.value YearPublished
from
Value v1
Join Value v2
on v2.type = 2
AND v2.value in ( 1822, 1835, 1912 )
AND v1.resource_id = v2.resource_id
where
v1.type = 1
v1.value = 'Moby Dick'
我会在您的 table 上(类型,值,resource_id)创建一个复合索引,而不是在每一列上创建单独的索引
现在让我们看看它在做什么。如果您查看查询的非常基本的部分,因为它只与“v1”别名有关,它正在寻找类型 = 1(代表标题),并且值是感兴趣的书的名称。你可能很容易就明白了。
所以现在您所做的就是为一年 written/published 添加一个额外的标准(或您的其他“类型”数据表明的任何内容)。这将再次连接到相同的 table,但别名不同。现在,对于关系,只需将那个标准放在那里,但除此之外,您还要确保 resource_id 与找到的第一个 v1 资源相同。
这里的好处是,您的外部主要查询将开始首先查找符合标题条件的数据,这将是一个有点小的列表。然后,只有从那个小列表中,它甚至关心是否存在由同一资源和您正在查找的附加查询(日期、年份或其他内容的列表)连接到第二个 table 的条件。
现在,如果您有其他类型为 3 的“值”,但不关心其中的值是什么,您只需再次加入值 table 作为 ex:别名 v3,但是只加入 v3.type = 3 and v1.resource_id = v3.resource_id
通过使用别名引用和值列,只需将最终列别名分配给它应该代表的内容,如此处所示。
如果对相同的值 table 执行第 3 次、第 4 次或更多次这样的操作,您可能需要在 (resource_id、类型、值) 上添加一个索引。是的,两个索引具有相同的列,但为了优化第 2、3、4 个 JOIN 条件目的。