2015-01-09 48 views
1

我想在PostgreSQL的查詢,其中列出我的用戶和他們的電子郵件地址和電話號碼(用逗號隔開),像這樣:SQL:列表中的用戶與他們的電話號碼和電子郵件地址

| user1 | [email protected], [email protected] | +3612123123, +3623234234 | 

的表是:

user - stores the user's data 

user_email - stores the user's email addresses 

user_phone - stores the user's phone numbers 

我試過obvius:

SELECT user.id, user.name 
(
    SELECT array_agg(user_email.email) 
    FROM user_email 
    WHERE user_email.user_id = user.id 
) AS EmailAddresses, 
(
    SELECT array_agg(user_phone.phone) 
    FROM user_phone 
    WHERE user_phone.user_id = user.id 
) AS PhoneNumbers 
FROM user 
ORDER BY user.id 

但這導致荒謬的查詢時間(34sec)。 比我試過:

SELECT user.id, user.name, array_agg(user_email.email), array_agg(user_phone.phone) 
FROM user 
LEFT JOIN user_email ON user_email.user_id = user.id 
LEFT JOIN user_phone ON user_phone.user_id = user.id 
GROUP BY user.id 
ORDER BY user.id 

這個結果非常好的查詢時間(大約100ms)。 但是,這種方式列出了電話號碼和電子郵件地址的每個組合。所以如果我有3個電子郵件地址和3個電話號碼,那麼它會列出9個電子郵件地址(每個地址的三倍)和9個電話號碼。

有沒有一種有效的方法來做我想要的?

回答

1

DISTINCT可以在aggregate expressions也可以使用:

SELECT "user".id, name, array_agg(DISTINCT email) emails, array_agg(DISTINCT phone) phones 
FROM "user" 
LEFT JOIN user_email ON user_email.user_id = "user".id 
LEFT JOIN user_phone ON user_phone.user_id = "user".id 
GROUP BY "user".id 
ORDER BY "user".id; 

注意:如果您只需要用逗號分隔的列表,則可能需要使用string_agg()而不是array_agg()

SQLFiddle

0

要麼DISTINCT

SELECT DISTINCT user.id, user.name, array_agg(user_email.email), array_agg(user_phone.phone) 
FROM user 
LEFT JOIN user_email ON user_email.user_id = user.id 
LEFT JOIN user_phone ON user_phone.user_id = user.id 
GROUP BY user.id 
ORDER BY user.id 

或者INNER加入

SELECT user.id, user.name, array_agg(user_email.email), array_agg(user_phone.phone) 
FROM user 
INNER JOIN user_email ON user_email.user_id = user.id 
INNER JOIN user_phone ON user_phone.user_id = user.id 
GROUP BY user.id 
ORDER BY user.id 

或者兩者

SELECT DISTINCT user.id, user.name, array_agg(user_email.email), array_agg(user_phone.phone) 
FROM user 
INNER JOIN user_email ON user_email.user_id = user.id 
INNER JOIN user_phone ON user_phone.user_id = user.id 
GROUP BY user.id 
ORDER BY user.id 
+0

如果您使用'group by',則不需要添加'distinct' –

相關問題