【问题标题】:Select data from one table based on selected rows in another根据另一个表中的选定行从一个表中选择数据
【发布时间】:2019-03-09 14:52:21
【问题描述】:

我有三张桌子:

书籍:

{id, title, status}
{1, SuperHero, false}
{2, Hobbit, true}
{3, Marvel, true}

标签:

{id, name}
{1, Drama}
{2, Comedy}
{3, Triller}

books_tags:

{book_id, tag_id}
{1, 1}
{1, 2}
{2, 2}

每本书都可以有或没有很多独特的标签。

1)基于 book_id 在一次查询中获取一本书的所有标签和数据(tag.id,名称)的正确方法是什么?

2)在一个查询中获取所有具有标题的书籍的正确方法是什么?

我为第一个想出了这个,但在第二个中挣扎:

SELECT tag_id, name 
FROM books_tags 
    INNER JOIN tags ON tag_id = tags.id 
WHERE book_id = 1

【问题讨论】:

    标签: sql database postgresql


    【解决方案1】:

    对于第二个要求,使用以下内容:

    SELECT
        b.title,
        array_agg(t.name) AS tags
    FROM books AS b
    INNER JOIN books_tags AS bt ON (b.id = bt.book_id)
    INNER JOIN tags AS t ON (bt.tag_id = t.id)
    WHERE b.status = true
    GROUP BY 1;
    

    【讨论】:

      【解决方案2】:

      在 Postgres 中,您可以使用 array type,在这种情况下,这可以让您的生活更轻松,并使 books_tags 表过时。

      考虑以下设置:

      create temp table if not exists tags(
          id   int, 
          name text
      );
      insert into tags(id, name)
      values  (1, 'Drama')
             ,(2, 'Comedy')
             ,(3, 'Thriller');
      
      create temp table if not exists books(
          id        int, 
          title     text, 
          status    bool,
          book_tags int[]
      );
      insert into books(id, title, status, book_tags)
      values  (1, 'SuperHero', false, array[1, 2])
             ,(2, 'Hobbit',    true,  array[2])
             ,(3, 'Marvel',    true,  null);
      

      现在您可以轻松地执行查询。例如1)

      select  book_tags
      from    books B 
      where   B.id = 1;
      

      如果您希望标签位于单独的行中,请使用unnest() 函数,例如

      select  unnest(book_tags)
      from    books B 
      where   B.id = 1;
      

      和 2) 查找所有带有 tag in [2]status = true 的书籍

      select  id, title, book_tags
      from    books B 
      where   B.status = true 
          and B.book_tags @> array[2]  -- set query tags in on right side
      

      您的样本数据包含第 1 册的 status=false,因此 array[1, 2] 不会使用该数据返回任何结果。因此,我将示例设置为仅使用一个标签。

      【讨论】:

      • 谢谢,但在这种情况下,如何按标签搜索所有书籍?速度快吗?
      • @RTW 我更新了答案。请记住,您的示例数据将第一本书设置为status=false,所以这让我暂时离开了
      • 但是性能呢?我敢肯定,如果您有 1.000.000 本书,并且每本书都有 5-20 个标签,那么如果您使用数组,那么通过某个标签搜索所有书会很慢?我什至不知道数组是否有索引...
      • 速度很快,因为你可以索引数组列,而且你不需要加入另一个表,节省了大量的处理能力
      • 最后我的选择不是数组,这个答案让我决定:stackoverflow.com/questions/43690430/…
      猜你喜欢
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-23
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 2015-02-15
      相关资源
      最近更新 更多