gpt4 book ai didi

sql - 一次选择形成大量多对多关系的最佳实践

转载 作者:行者123 更新时间:2023-11-29 12:09:33 26 4
gpt4 key购买 nike

我想知道处理以下问题的最佳方法是什么:

我有一个 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"
]
}
]

最佳答案

访问数据库一次通常是最好的。您应该预先聚合每个维度的值:

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。

关于sql - 一次选择形成大量多对多关系的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43822080/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com