我正在爲我的Web構建數據進行建模。我使用Postgresql數據庫。建模SQL中的Post和Flag關係
在應用程序中有像SO帖子這樣的帖子,還有帖子的標誌作爲Github標誌或標記,無論正確的術語是什麼。一個帖子一次只能有一個標誌。有很多職位不斷增加,但是有四五個職位,他們不會增加。
第一種方法,歸一化;我用三張表格模擬了我的這部分數據;兩個用於相應的實體帖子和標誌,另一個用於關係爲post_flag。任何實體表中沒有提及其他實體表中的關係。所有的關係都被記錄在關係表post_flag中,並且這僅僅是用於帖子和標誌的id的id對。在這種情況下
表的結構將是:
CREATE TABLE posts
(
id bigserial PRIMARY KEY,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
title character varying(100),
text text,
score integer DEFAULT 0,
author_id integer NOT NULL REFERENCES users (id),
product_id integer NOT NULL REFERENCES products (id),
);
CREATE TABLE flags
(
id bigserial PRIMARY KEY,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
flag character varying(30) NOT NULL -- planned, in progress, fixed
);
CREATE TABLE post_flag
(
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
post_id integer NOT NULL REFERENCES posts (id),
flag_id integer NOT NULL REFERENCES flags (id)
);
要獲得標記的職位爲固定我必須使用:
-- homepage posts- fixed posts tab
SELECT
p.*,
f.flag
FROM posts p
JOIN post_flag p_f
ON p.id = p_f.post_id
JOIN flags f
ON p_f.flag_id = f.id
WHERE f.flag = 'fixed'
ORDER BY p_f.created_at DESC
第二條本辦法;我有兩個表格文章和標誌。表格帖子有一個flag_id列,它引用flags表中的一個標誌。
CREATE TABLE posts
(
id bigserial PRIMARY KEY,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
title character varying(100),
text text,
score integer DEFAULT 0,
author_id integer NOT NULL REFERENCES users (id),
product_id integer NOT NULL REFERENCES products (id),
flag_id integer DEFAULT NULL REFERENCES flags (id)
);
CREATE TABLE flags
(
id bigserial PRIMARY KEY,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
flag character varying(30) NOT NULL -- one of planned, in progress, fixed
);
對於相同的數據;
-- homepage posts- fixed posts tab
SELECT
p.*,
f.flag
FROM posts p
JOIN flags f
ON p.flag_id = f.id
WHERE f.flag = 'fixed'
ORDER BY p.created_at DESC
第三種方法規格化;我只有一個表格文章。職位表有一個標誌列來存儲分配給職位的標誌。
CREATE TABLE posts
(
id bigserial PRIMARY KEY,
created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
title character varying(100),
text text,
score integer DEFAULT 0,
author_id integer NOT NULL REFERENCES users (id),
product_id integer NOT NULL REFERENCES products (id),
flag character varying(30)
);
在這裏,我只會有相同的數據;
-- homepage posts- fixed posts tab
SELECT
p.*,
FROM posts p
WHERE p.flag = 'fixed'
ORDER BY p.created_at DESC
我不知道如果第一種方法在像Postgresql這樣的RDBMS中的數據規範化方面是過度殺傷性的嗎?對於後評論關係,第一種方法會很棒,而且我的確使用它。但是我有一些很少的數量數據用作徽章,標誌,標籤等帖子的元數據。正如你所看到的事實上是最正常的形式,第一種方法,我已經使用一些product_id等使用一個較少的JOIN
,但另一個表作爲不同的關係,而不是標誌。所以,我的方法適合我的第二種方法。我應該使用更加非規範化的方法,第三種方法是在其中添加張貼表和標誌欄?在性能,擴展和可維護性方面有哪些更好的方法?
它可能只是我,但看到你的不同表結構會比看到你用來對付它們的查詢在評估規範化程度和效果時更有益。 – alzee
添加了數據結構。 –