【问题标题】:Generate data with at least one occurence生成至少出现一次的数据
【发布时间】:2021-06-24 03:30:35
【问题描述】:

我有三张桌子:

create table genres
(
genre_id serial primary key,
genre_name varchar NOT NULL UNIQUE
);

create table movies
(
movie_id serial primary key,
movie_name varchar NOT NULL           
);

create table movie_genres
(
movie_id integer references movies NOT NULL,
genre_id integer references genres NOT NULL, 
PRIMARY KEY(movie_id, genre_id)
);

表流派和电影充满了数据,我想为表movie_genres生成一些随机数据,以便每部电影至少有一个流派。 我尝试过这种方式,但是一部电影可能没有任何类型。谁能帮帮我,好吗?

insert into movie_genres 
select movie_id, genre_id 
from genres cross join movies 
where random() < 0.15;

【问题讨论】:

    标签: postgresql generate


    【解决方案1】:

    嗯,您可以尝试加入一个派生表,在该表中先选择一个随机流派,然后再随机选择UNION

    INSERT INTO movie_genres 
            (movie_id,
             genre_id)
    SELECT m.movie_id,
           rg.genre_id
           FROM movies m
                CROSS JOIN ((SELECT g.genre_id
                                    FROM genres g
                                    ORDER BY random()
                                    LIMIT 1)
                            UNION
                            (SELECT g.genre_id
                                    FROM genres g
                                    WHERE random() < 0.15)) rg;
    

    然而,这意味着每部电影都会首先选择一种类型。为了克服这个问题并让每部电影的第一种类型是随机的,可以使用横向连接。 (备注:您需要在派生表中使用外部表中的某些列,否则优化器似乎将LATERAL 优化掉。)

    INSERT INTO movie_genres 
                (movie_id,
                 genre_id)
    SELECT rg.movie_id,
           rg.genre_id
           FROM movies m
                CROSS JOIN LATERAL ((SELECT g.genre_id,
                                            m.movie_id -- that's just here to force the optimizer to keep the join lateral
                                            FROM genres g
                                            ORDER BY random()
                                            LIMIT 1)
                                    UNION
                                    (SELECT g.genre_id,
                                            m.movie_id
                                            FROM genres g
                                            WHERE random() < 0.15)) rg;
    

    db<>fiddle

    【讨论】:

    • SELECT rg.* FROM … 使movie_id 选择有意义
    • @Bergi:我不明白你的评论?对于INSERT,我们只需要派生表中的genre_id。请参阅我关于 movie_id 为何在其中的评论。
    • 是的,我明白这一点,但如果 rg.movie_id 没有在任何地方使用,那么是什么让优化器也无法将其删除?我建议在实际的 INSERT 语句中使用该列,而不是 m.movie_id
    • @Bergi:公平点!我将其更改为使用派生表中的movie_id
    猜你喜欢
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 2018-12-21
    相关资源
    最近更新 更多