2017-05-06 29 views
2

我想知道什麼是處理好以下幾個問題的最好辦法:選擇形成了很多很多一對多關係的一次最佳實踐

我有一個DB-結構,其中許多表鏈接我的Person表是這樣的:

phone n-n person_phone_realtion n-n person n-n person_email_realtionn-n email 

我想查詢我的表和分析結果,以JSON和衆多的存儲很多值陣列內。是否更好地只做一次數據庫訪問,並將我的JOIN查詢的結果(請參見下面的示例)解析爲我想要的模式,或者我應該更多地訪問數據庫並保留查詢結果很小?

,這是什麼情況

創建與下面的語句的最佳實踐:

DROP TABLE IF EXISTS phone CASCADE; 
DROP TABLE IF EXISTS email CASCADE; 
DROP TABLE IF EXISTS person CASCADE; 
DROP TABLE IF EXISTS person_phone_realtion CASCADE; 
DROP TABLE IF EXISTS person_email_realtion CASCADE; 

CREATE TABLE phone (
    phon_id text NOT NULL, 
    CONSTRAINT phone_pk PRIMARY KEY (phon_id) 
); 

CREATE TABLE email (
    emai_id text NOT NULL, 
    CONSTRAINT email_pk PRIMARY KEY (emai_id) 
); 

CREATE TABLE person (
    pers_id INTEGER NOT NULL, 
    CONSTRAINT person_pk PRIMARY KEY (pers_id) 
); 

CREATE TABLE person_phone_realtion (
    pers_id int NOT NULL, 
    phon_id int NOT NULL 
); 

CREATE TABLE person_email_realtion (
    pers_id int NOT NULL, 
    email_id int NOT NULL 
); 

INSERT INTO person(pers_id) 
VALUES (1),(2),(3),(4),(5); 

INSERT INTO email(emai_id) 
VALUES ('a'),('b'),('c'); 

INSERT INTO phone(phon_id) 
VALUES ('D'),('E'),('F'); 

INSERT INTO person_email_realtion(pers_id, email_id) 
VALUES (1,'a'),(1,'b'), (1,'c'),(2,'b'),(3,'c'); 

INSERT INTO person_phone_realtion(pers_id, phon_id) 
VALUES (1,'D'),(2,'D'), (2,'E'),(5,'F'); 

DROP TABLE IF EXISTS phone CASCADE; 
DROP TABLE IF EXISTS email CASCADE; 
DROP TABLE IF EXISTS person CASCADE; 
DROP TABLE IF EXISTS person_phone_realtion CASCADE; 
DROP TABLE IF EXISTS person_email_realtion CASCADE; 

CREATE TABLE phone (
    phon_id text NOT NULL, 
    CONSTRAINT phone_pk PRIMARY KEY (phon_id) 
); 

CREATE TABLE email (
    emai_id text NOT NULL, 
    CONSTRAINT email_pk PRIMARY KEY (emai_id) 
); 

CREATE TABLE person (
    pers_id INTEGER NOT NULL, 
    CONSTRAINT person_pk PRIMARY KEY (pers_id) 
); 

CREATE TABLE person_phone_realtion (
    pers_id int NOT NULL, 
    phon_id int NOT NULL 
); 

CREATE TABLE person_email_realtion (
    pers_id int NOT NULL, 
    email_id int NOT NULL 
); 

INSERT INTO person(pers_id) 
VALUES (1),(2),(3),(4),(5); 

INSERT INTO email(emai_id) 
VALUES ('a'),('b'),('c'); 

INSERT INTO phone(phon_id) 
VALUES ('D'),('E'),('F'); 

INSERT INTO person_email_realtion(pers_id, email_id) 
VALUES (1,'a'),(1,'b'), (1,'c'),(2,'b'),(3,'c'); 

INSERT INTO person_phone_realtion(pers_id, phon_id) 
VALUES (1,'D'),(2,'D'), (2,'E'),(5,'F'); 

現在我可以一次使用JOIN至極會導致大量的重複內容查詢所有關係:

SELECT * FROM person 
RIGHT JOIN person_phone_realtion 
ON person.pers_id = person_phone_realtion.pers_id 
RIGHT JOIN phone 
ON person_phone_realtion.phon_id = phone.phon_id 
RIGHT JOIN person_email_realtion 
ON person.pers_id = person_email_realtion.pers_id 
RIGHT JOIN email 
ON person_email_realtion.email_id = email.emai_id; 

在那裏我會得到類似這樣的結果:

pers_id phon_id emai_id 
1  D  a 
1  D  b 
1  D  c 
2  E  b 
2  D  b 

產生的JSON應該是這樣的:

[ 
    { 
     "person" : 1, 
     "email": [ 
      "a", "b", "c" 
     ], 
     "phone":[ 
      "D" 
     ] 
    }, 
    { 
     "person" : 2, 
     "email": [ 
      "b" 
     ], 
     "phone":[ 
      "D", "E" 
     ] 
    } 
] 
+0

請描述你想要的結果集。你真的想要轉儲數據庫中的所有數據嗎? –

+0

@GordonLinoff我添加了JSON-Schema我想在最後達到 –

回答

2

一個訪問數據庫通常是最好的。您應該預先聚合每個維度的值:

select p.*, pp.phones, pe.emails 
from person p left join 
    (select pers_id, array_agg(ppr.phone_id) as phones 
     from person_phone_realtion ppr 
     group by pers_id 
    ) pp 
    on p.pers_id = pp.pers_id left join 
    (select pers_id, array_agg(per.email_id) as emails 
     from person_email_realtion ppr 
     group by pers_id 
    ) pe 
    on p.pers_id = pe.pers_id ; 

如果您願意,可以聚合爲字符串或JSON。

+0

哇謝謝!這有很大幫助。我不知道你可以在SQL中彙總數據,而你的例子有竅門。 –