如何从此数据库布局的 1:M 关系中删除冗余并仍然能够摘录所需的数据?
How do I remove redundancy from this database layout's 1:M relationship and still be able to excerpt the data needed?
数据库如下所示:
CREATE TABLE artists (
artist_id SERIAL PRIMARY KEY,
artist TEXT UNIQUE NOT NULL
);
CREATE TABLE artistalias (
artistalias_id SERIAL PRIMARY KEY,
artist_id SERIAL REFERENCES artists (artist_id),
alias TEXT UNIQUE NOT NULL
);
CREATE TABLE songs (
song_id SERIAL PRIMARY KEY,
song TEXT NOT NULL,
artist_id SERIAL REFERENCES artists (artist_id)
);
- 一位艺术家可以有零个、一个或多个别名
- 一个别名只属于一位艺术家
- 一首歌有一个艺术家
- 一个艺术家可以拥有一首或多首歌曲
我的问题是数据库中包含使用两个或更多 假名的艺术家。例如,一位艺术家使用艺名 Assassin 来表示属于某一流派的歌曲,而使用名称 Agent Sasco 来表示属于另一种流派的歌曲。
有些艺人只是时不时地随便改个笔名。
稍后网站应按以下格式显示数据:
Artist | Song
------------+-------------------
Assassin | Anywhere We Go
Agent Sasco | We Dem A Watch
当您单击艺术家时,它会 link 您进入一个页面,该页面显示该艺术家用于表演歌曲的所有不同别名。
重要的是,歌曲以发行时所用的艺术家的笔名显示。
我使用的虚拟数据如下所示:
INSERT INTO artists (artist) VALUES
('Assassin'), ('Agent Sasco'), ('Sizzla');
-- This bothers me as its a lot of redundant data
INSERT INTO artistalias (artist_id, alias) VALUES
(1, 'Agent Sasco'), (2, 'Assassin');
INSERT INTO songs (song, artist_id) VALUES
('Anywhere We Go', 1), ('We Dem A Watch', 2), ('Only Takes Love', 3);
这个数据库布局困扰我的是我必须向 artistalias
添加冗余数据。必须有更好的方法将 link table artists
到 artistalias
和 songs
而不必多次添加一个特定的艺术家和他的别名?
以所需格式显示数据的查询如下所示:
SELECT
artist AS pseudonyme_song_was_performed_with,
string_agg(alias, ' & ') AS other_pseudonymes,
song
FROM
artists
left JOIN artistalias USING (artist_id)
left JOIN songs USING (artist_id)
GROUP BY artist, song;
这里是 SQLFiddle 布局和数据如上所述。
您应该在 artists
table 中存储艺术家的真实姓名。
然后将该艺术家的所有别名存储在 artistalias
table。
然后将 artistalias_id 存储在 songs
table 中。
这样,您将不会有任何重复数据。
CREATE TABLE artists (
artist_id SERIAL PRIMARY KEY,
artist TEXT UNIQUE NOT NULL
);
CREATE TABLE artistalias (
artistalias_id SERIAL PRIMARY KEY,
artist_id SERIAL REFERENCES artists (artist_id),
alias TEXT UNIQUE NOT NULL
);
CREATE TABLE songs (
song_id SERIAL PRIMARY KEY,
song TEXT NOT NULL,
artistalias_id SERIAL REFERENCES artistalias (artistalias_id)
);
然后这样插入数据:
INSERT INTO artists (artist) VALUES
('Jeffrey Campbell'), ('Sizzla');
-- THIS REDUNDANCY IS BOTHERING ME
INSERT INTO artistalias (artist_id, alias) VALUES
(1, 'Agent Sasco'), (1, 'Assassin');
INSERT INTO songs (song, artistalias_id) VALUES
('Anywhere We Go', 1), ('We Dem A Watch', 2);
并这样查询:
SELECT
a1.alias AS pseudonyme_song_was_performed_with,
string_agg(a2.alias, ' & ') AS other_pseudonymes,
song
FROM
artistalias a1
left JOIN artistalias a2 on a2.artist_id = a1.artist_id
left JOIN songs s on s.artistalias_id = a1.artistalias_id
GROUP BY a1.alias, song;
数据库如下所示:
CREATE TABLE artists (
artist_id SERIAL PRIMARY KEY,
artist TEXT UNIQUE NOT NULL
);
CREATE TABLE artistalias (
artistalias_id SERIAL PRIMARY KEY,
artist_id SERIAL REFERENCES artists (artist_id),
alias TEXT UNIQUE NOT NULL
);
CREATE TABLE songs (
song_id SERIAL PRIMARY KEY,
song TEXT NOT NULL,
artist_id SERIAL REFERENCES artists (artist_id)
);
- 一位艺术家可以有零个、一个或多个别名
- 一个别名只属于一位艺术家
- 一首歌有一个艺术家
- 一个艺术家可以拥有一首或多首歌曲
我的问题是数据库中包含使用两个或更多 假名的艺术家。例如,一位艺术家使用艺名 Assassin 来表示属于某一流派的歌曲,而使用名称 Agent Sasco 来表示属于另一种流派的歌曲。 有些艺人只是时不时地随便改个笔名。
稍后网站应按以下格式显示数据:
Artist | Song
------------+-------------------
Assassin | Anywhere We Go
Agent Sasco | We Dem A Watch
当您单击艺术家时,它会 link 您进入一个页面,该页面显示该艺术家用于表演歌曲的所有不同别名。 重要的是,歌曲以发行时所用的艺术家的笔名显示。
我使用的虚拟数据如下所示:
INSERT INTO artists (artist) VALUES
('Assassin'), ('Agent Sasco'), ('Sizzla');
-- This bothers me as its a lot of redundant data
INSERT INTO artistalias (artist_id, alias) VALUES
(1, 'Agent Sasco'), (2, 'Assassin');
INSERT INTO songs (song, artist_id) VALUES
('Anywhere We Go', 1), ('We Dem A Watch', 2), ('Only Takes Love', 3);
这个数据库布局困扰我的是我必须向 artistalias
添加冗余数据。必须有更好的方法将 link table artists
到 artistalias
和 songs
而不必多次添加一个特定的艺术家和他的别名?
以所需格式显示数据的查询如下所示:
SELECT
artist AS pseudonyme_song_was_performed_with,
string_agg(alias, ' & ') AS other_pseudonymes,
song
FROM
artists
left JOIN artistalias USING (artist_id)
left JOIN songs USING (artist_id)
GROUP BY artist, song;
这里是 SQLFiddle 布局和数据如上所述。
您应该在 artists
table 中存储艺术家的真实姓名。
然后将该艺术家的所有别名存储在 artistalias
table。
然后将 artistalias_id 存储在 songs
table 中。
这样,您将不会有任何重复数据。
CREATE TABLE artists (
artist_id SERIAL PRIMARY KEY,
artist TEXT UNIQUE NOT NULL
);
CREATE TABLE artistalias (
artistalias_id SERIAL PRIMARY KEY,
artist_id SERIAL REFERENCES artists (artist_id),
alias TEXT UNIQUE NOT NULL
);
CREATE TABLE songs (
song_id SERIAL PRIMARY KEY,
song TEXT NOT NULL,
artistalias_id SERIAL REFERENCES artistalias (artistalias_id)
);
然后这样插入数据:
INSERT INTO artists (artist) VALUES
('Jeffrey Campbell'), ('Sizzla');
-- THIS REDUNDANCY IS BOTHERING ME
INSERT INTO artistalias (artist_id, alias) VALUES
(1, 'Agent Sasco'), (1, 'Assassin');
INSERT INTO songs (song, artistalias_id) VALUES
('Anywhere We Go', 1), ('We Dem A Watch', 2);
并这样查询:
SELECT
a1.alias AS pseudonyme_song_was_performed_with,
string_agg(a2.alias, ' & ') AS other_pseudonymes,
song
FROM
artistalias a1
left JOIN artistalias a2 on a2.artist_id = a1.artist_id
left JOIN songs s on s.artistalias_id = a1.artistalias_id
GROUP BY a1.alias, song;