连接表并计算不同值的实例

时间:2016-03-03 22:41:17

标签: postgresql join

user
---------------------------
| ID | Name               |
---------------------------
| 1  | Jim Rice           |
| 2  | Wade Boggs         |
| 3  | Bill Buckner       |
---------------------------

at_bats
----------------------
| ID | User |  Bases |
----------------------
| 1  | 1    | 2      |
| 2  | 2    | 1      |
| 3  | 1    | 2      |
| 4  | 3    | 0      |
| 5  | 1    | 3      |
----------------------

我希望我的查询要做的是获取连接表中不同基值的计数,如:

count_of_hits
---------------------
| ID | 1B | 2B | 3B |
---------------------
| 1  | 0  | 2  | 1  |
| 2  | 1  | 0  | 0  |
| 3  | 0  | 0  | 0  |
---------------------

我有一个查询,我可以单独获得基础,但不是所有,除非我做了一些复杂的连接,我想有更好的方法。这是基本的问题:

SELECT id, COUNT(ab.*)
FROM user
LEFT OUTER JOIN (SELECT * FROM at_bats WHERE at_bats.bases=2) ab ON ab.user=user.id

2 个答案:

答案 0 :(得分:1)

我认为以下查询可以解决您的问题。但是,我不确定这是否是最佳方法:

select distinct a.users, coalesce(b.B1, 0) As B1, coalesce(c.B2, 0) As B2 ,coalesce(d.B3, 0) As B3
    FROM at_bats a
    LEFT JOIN (SELECT users, count(bases) As B1 FROM at_bats WHERE bases = 1 GROUP BY users) as b ON  a.users=b.users
    LEFT JOIN (SELECT users, count(bases) As B2 FROM at_bats WHERE bases = 2 GROUP BY users) as c ON  a.users=c.users
    LEFT JOIN (SELECT users, count(bases) As B3 FROM at_bats WHERE bases = 3 GROUP BY users) as d ON  a.users=d.users
    Order by users

coalesce()函数只是用零替换空值。我希望这个查询可以帮助你:D

更新1

我找到了一种更好的方法,请查看以下内容:

SELECT users,
count(case bases when 1 then 1 else null end) As B1,
count(case bases when 2 then 1 else null end) As B2,
count(case bases when 3 then 1 else null end) As B3
FROM at_bats
GROUP BY users
ORDER BY users;

与我的第一个查询相比,它更有效。您可以在查询之前使用EXPLAIN ANALYSE检查性能。 感谢Guffa发表的帖子:https://stackoverflow.com/a/1400115/4453190

答案 1 :(得分:1)

PostgreSQL 9.4+提供了一种更清晰的方法:

SELECT 
  users,
  count(*) FILTER (WHERE bases=1) As B1,
  count(*) FILTER (WHERE bases=2) As B2,
  count(*) FILTER (WHERE bases=3) As B3,
FROM at_bats
GROUP BY users
ORDER BY users;