结合两个查询postgres的结果

时间:2016-11-07 12:23:07

标签: sql postgresql aggregate postgresql-9.1

我有两个这样的问题:

SELECT project_id, user_ip, count(*) AS Count 
FROM "user" 
WHERE user_ip IS NOT NULL 
GROUP BY user_ip, project_id;

SELECT project_id, user_id, count(*) AS Count 
FROM "user" 
WHERE user_id IS NOT NULL 
GROUP BY user_id, project_id;

它们都是相同的,除了一个返回基于IP和其他ID的用户。

用户只能拥有其中一项,所以基本上如果user_ipNull,那么user_id会有价值,如果user_idNull则相反 那么user_ip就会有价值。

所以我想要的是将这些查询作为一个查询。

第一个查询给出了这个:

project_id | user_ip | Count            
  1        | 1.2.3.4 | 40        
  2        | 1.2.3.5 | 25    
  3        | 1.2.3.6 | 9          
  4        | 1.2.3.7 | 7 

第二个给出了这个:

project_id | user_id | Count            
  1        |  1234   | 100        
  2        |  4567   | 50    
  3        |  4321   | 49  

所以我想只做一个会返回这个的查询:

project_id | user_id | user_ip | Count            
  1        |  1234   |         | 100 
  1        |         | 1.2.3.4 | 40       
  2        |  4567   |         | 50
  2        |         | 1.2.3.5 | 25     
  3        |  4321   |         | 49 
  3        |         | 1.2.3.6 | 9          
  4        |         | 1.2.3.7 | 7

我尝试做左连接也尝试用Union做但我得错误:UNION types text and integer cannot be matched

SELECT project_id, user_ip, count(*) AS Count 
FROM "user" 
WHERE user_ip IS NOT NULL 
GROUP BY user_ip, project_id  
UNION 
SELECT project_id, user_id, count(*) AS Count 
FROM "user" 
WHERE user_id IS NOT NULL GROUP 
BY user_id, project_id;

有人可以帮我实现我想要的结果吗?我可以用什么?

4 个答案:

答案 0 :(得分:2)

union的查询需要具有相同数量和类型的所有列。试试这个:

SELECT project_id, user_ip, null as user_id, count(*) AS Count FROM "user" WHERE user_ip IS NOT NULL GROUP BY user_ip, project_id  
UNION 
SELECT project_id, null as user_ip, user_id, count(*) AS Count FROM "user" WHERE user_id IS NOT NULL GROUP BY user_id, project_id;

答案 1 :(得分:1)

在投影中的SELECT子句中添加NULL as user_id/ip

SELECT project_id, NULL as user_id, user_ip, count(*) AS Count ...
union
SELECT project_id, user_id, NULL as user_ip, count(*) AS Count 

或者代替工会,试试group by project_id, user_id, user_ip,这也应该有效。这可能会更快。

SELECT project_id, user_id, user_ip, count(*) AS Count 
FROM "user" 
GROUP BY project_id, user_id, user_ip;

答案 2 :(得分:0)

首先,使用union all。其次,将值转换为文本...一个是数字,另一个是字符串:

SELECT project_id, user_ip::text, count(*) AS Count 
FROM "user" 
WHERE user_ip IS NOT NULL 
GROUP BY user_ip, project_id  
UNION ALL
SELECT project_id, user_id::text, count(*) AS Count 
FROM "user" 
WHERE user_id IS NOT NULL
GROUP BY user_id, project_id;

你也可以在Postgres 9.5 +中使用GROUPING SETS来写这个:

SELECT project_id, COALESCE(user_ip::text, user_id::text),
       count(*) AS Count 
FROM "user" 
WHERE user_ip IS NOT NULL 
GROUP BY GROUPING SETS ((project_id, user_ip), (project_id, user_id))

答案 3 :(得分:0)

Grouping sets(9.5 +)

select *
from (
    select project_id, user_id, user_ip, count(*)
    from "user"
    group by grouping sets ((project_id, user_id), (project_id, user_ip))
) s
where user_id is not null or user_ip is not null