根据另一个表中的选定行从一个表中选择数据

问题描述 投票:1回答:2

我有三张桌子:

图书:

{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,name)的正确方法是什么?

2)在一个查询中,每个书行的标签数组以状态(true)获取所有书籍的正确方法是什么?

我为第一个提出这个问题,但是在第二个问题上挣扎:

SELECT tag_id, name 
FROM books_tags 
    INNER JOIN tags ON tag_id = tags.id 
WHERE book_id = 1
sql database postgresql
2个回答
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;

1
投票

在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]不会带回任何带有该数据的结果。因此,我将我的示例设置为仅使用一个标记。

© www.soinside.com 2019 - 2024. All rights reserved.