计算包括 0 连接两个具有不同行 postgres 的表

Count including 0 on join two tables with different rows postgres

我有两个 table,用户 table 包含我系统中的所有用户和其他 table 调用的操作,包含我系统中用户完成的所有操作,我想要得到的是一个查询,我可以在其中计算用户的操作,如果我对一个用户没有任何操作,则获取 0。

我的两个 table:

Users Table:

Name       Place
----------------------
James      Supermarket
Alex       Bank 
Ignatius   BookShop

Action table:

Name   Action
--------------------
James  Buy
James  Buy
Alex   Complaint
Alex   Buy
Alex   Buy

我想要这样的东西:

Name       Transactions   Place
-------------------------------
James      2              Supermarket
Alex       3              Bank
Ignatius   0              BookShop

我试过:

SELECT users.name, 
   (SELECT Count(action.name) 
    FROM   action, 
           users 
    WHERE  action.name = users.name 
    GROUP  BY action.name) 
    users.place
FROM 
action, 
users 
WHERE  action.name = users.name 

但总是给我这个错误:

ERROR: more than one row returned by a subquery used as an expression SQL state: 21000

知道怎么做吗?

您应该先进行左连接,然后将 group by 应用于其结果:

SELECT
    u.name
,   COUNT(a.name) AS Transactions
,   u.place
FROM users u
LEFT OUTER JOIN action a ON a.name = u.name 
GROUP BY u.name, u.place

左连接确保用户记录不会被丢弃,即使它在 action table.

中没有关联事务

从不FROM 子句中使用逗号。始终使用正确、明确的 JOIN 语法。也就是说,如果您想使用相关子查询,则此查询根本不需要任何连接:

SELECT u.name, 
       (SELECT Count(*) 
        FROM action a 
        WHERE a.name = u.name 
       ) as cnt,
       u.place
FROM users u;

为了性能,您需要 action(name) 上的索引。使用这样的索引,这可能比使用 left joingroup by.

的替代版本更快

备注:

  • 所有 table 都有 table 别名,是 table 名字的缩写。
  • 此版本的查询不需要连接。
  • 子查询中没有 group by
  • 外部查询中不需要 where 子句。

与之前的回答一样,左连接可以帮助您解决问题。 如果你想在结果中包含位置,那么在总结后做左连接

SELECT a.name,
        ISNULL(b.cnt, 0) AS Transactions,
        a.place
FROM users a
LEFT JOIN
   (SELECT name,
            Count(name) cnt
    FROM   action 
    GROUP  BY name) b
ON a.name =  b.name