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 条件目的。