创建一个返回动态结果的查询的最佳方法是什么,在我的postgresql中我有三个表:
contacts |contact_emails| contact_numbers
id | id | id
descrip | id_contact | id_contact
name | email | number
我希望创建一个类似的结果:
contact_name| contact_emailx| contact_numbersx
那些“x”是电子邮件和可以有联系人的号码
我正在尝试使用左连接,这是我的代码:
SELECT c.id, c.contact_name, cn.number, ce.email
FROM contacts c
LEFT JOIN contact_numbers cn ON c.id = cn.contact_id
LEFT JOIN contact_emails ce ON c.id = ce.contact_id
WHERE c.user_id = 1
我期待的是:
contact_name |number1 | number2 |email
LA MEJOR | 25445877| 25845877 |AMEJOR@GMAIL.COM
或
contact_name |number1 | number2 |email1 | email2
EDIFICADORA JUANA| 24602254| 55655545 |oipoa@gmaio.com |rst008@guan.com
我感谢任何帮助!
答案 0 :(得分:3)
您可以使用PostgreSQL array_agg
将所有电子邮件和所有数字汇总到两个数组中:
SELECT
c.id, c.contact_name, array_agg(DISTINCT cn.number) AS numbers, array_agg(DISTINCT ce.email) AS emails
FROM
contacts c
LEFT JOIN contact_numbers cn ON c.id = cn.contact_id
LEFT JOIN contact_emails ce ON c.id = ce.contact_id
WHERE
c.user_id = 1
GROUP BY
c.id
ORDER BY
c.id ;
id | contact_name | numbers | emails -: | :---------------- | :------------------ | :---------------------------------- 2 | LA MEJOR | {25445877} | {AHEJOR@GMAIL.COM,AMEJOR@GMAIL.COM} 3 | EDIFICADORA JUANA | {24602254} | {oipoa@gmaio.com,rst008@guan.com} 4 | EDIFICADORA JUANA | {24602254,55655545} | {oipoa@gmaio.com,rst008@guan.com} 5 | EDIFICADORA JUANA | {24602254,55655545} | {oipoa@gmaio.com,rst008@guan.com}
作为替代方案,您可以使用子查询(在某些情况下可能更快):
SELECT
c.id, c.contact_name,
(SELECT array_agg(DISTINCT cn.number) FROM contact_numbers cn WHERE cn.contact_id = c.id) AS numbers,
(SELECT array_agg(DISTINCT ce.email) FROM contact_emails ce WHERE ce.contact_id = c.id) AS emails
FROM
contacts c
WHERE
c.user_id = 1
ORDER BY
c.id ;
id | contact_name | numbers | emails -: | :---------------- | :------------------ | :---------------------------------- 2 | LA MEJOR | {25445877} | {AHEJOR@GMAIL.COM,AMEJOR@GMAIL.COM} 3 | EDIFICADORA JUANA | {24602254} | {oipoa@gmaio.com,rst008@guan.com} 4 | EDIFICADORA JUANA | {24602254,55655545} | {oipoa@gmaio.com,rst008@guan.com} 5 | EDIFICADORA JUANA | {24602254,55655545} | {oipoa@gmaio.com,rst008@guan.com}
如果你想分开(第一个)两个电子邮件和号码,你可以通过结束上一个查询来完成:
SELECT
id, contact_name,
numbers[1] AS number1,
numbers[2] AS number2,
emails[1] AS email1,
emails[2] AS email2
FROM
(
SELECT
c.id, c.contact_name,
(SELECT array_agg(DISTINCT cn.number) FROM contact_numbers cn WHERE cn.contact_id = c.id) AS numbers,
(SELECT array_agg(DISTINCT ce.email) FROM contact_emails ce WHERE ce.contact_id = c.id) AS emails
FROM
contacts c
WHERE
c.user_id = 1
) AS q
ORDER BY
id ;
id | contact_name | number1 | number2 | email1 | email2 -: | :---------------- | -------: | -------: | :--------------- | :--------------- 2 | LA MEJOR | 25445877 | null | AHEJOR@GMAIL.COM | AMEJOR@GMAIL.COM 3 | EDIFICADORA JUANA | 24602254 | null | oipoa@gmaio.com | rst008@guan.com 4 | EDIFICADORA JUANA | 24602254 | 55655545 | oipoa@gmaio.com | rst008@guan.com 5 | EDIFICADORA JUANA | 24602254 | 55655545 | oipoa@gmaio.com | rst008@guan.com
您可以在 dbfiddle here
在线查看所有内容使用的表格和数据:
CREATE TABLE contacts
(
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL /* REFERENCES users(id) */,
descrip text,
contact_name character varying(255)
) ;
CREATE TABLE contact_emails
(
contact_id INTEGER NOT NULL REFERENCES contacts(id),
email character varying(255) NOT NULL,
PRIMARY KEY(contact_id, email) -- This is the natural key for this table, no need for synthetic id
) ;
CREATE TABLE contact_numbers
(
contact_id INTEGER NOT NULL REFERENCES contacts(id),
number integer,
PRIMARY KEY(contact_id, number) -- Again...
) ;
...和数据
INSERT INTO
contacts
(id, user_id, descrip, contact_name)
VALUES
(2, 1, '', 'LA MEJOR'),
(3, 1, '', 'EDIFICADORA JUANA'),
(4, 1, '', 'EDIFICADORA JUANA'),
(5, 1, '', 'EDIFICADORA JUANA') ;
INSERT INTO
contact_emails
(contact_id, email)
VALUES
(2, 'AMEJOR@GMAIL.COM'),
(2, 'AHEJOR@GMAIL.COM'),
(3, 'oipoa@gmaio.com'),
(3, 'rst008@guan.com'),
(4, 'oipoa@gmaio.com'),
(4, 'rst008@guan.com'),
(5, 'oipoa@gmaio.com'),
(5, 'rst008@guan.com') ;
INSERT INTO
contact_numbers
(contact_id, number)
VALUES
(2, '25445877'),
(3, '24602254'),
(4, '24602254'),
(4, '55655545'),
(5, '24602254'),
(5, '55655545') ;
注意:图像数据中存在大量重复值。