结合两个查询postgres的结果

Combine results of two queries postgres

我有两个这样的查询:

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;

除了一个return是基于IP的用户,另一个是ID的用户外,它们都是一样的。

用户只能拥有其中一个,所以基本上如果 user_ipNull 那么 user_id 将有价值,如果 user_id 是 [=16] 则相反=] 那么 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  

所以我只想进行一个查询 return 这个:

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;

有人可以帮助我达到我想要的结果吗?我能用什么?

首先,使用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))

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

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;

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

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;

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