【问题标题】:postgressql/typeorm - Count with filter on same table and join with anotherpostgresql/typeorm - 在同一张表上使用过滤器计数并与另一个表连接
【发布时间】:2021-08-17 07:21:50
【问题描述】:

我正在使用 PostgresSQL 作为 DBMS 和 typeorm 作为 ORM 我需要写一个对我来说有点复杂的查询。 数据库结构如下所示:

Results
| PersonId | Result   |
|----------|----------|
| 1        | Rejected |
| 1        | Rejected |
| 1        | Passed   |
| 1        | Passed   |
| 2        | Rejected |
| 2        | Passed   |
| 3        | Rejected |
| 3        | Rejected |
| 3        | Rejected |
| 3        | Rejected |
| 3        | Passed   |

OtherTable
| PersonId | OtherColumn |
|----------|-------------|
| 1        | ...         |
| 1        | ...         |
| 1        | ...         |
| 2        | ...         |
| 2        | ...         |
| 3        | ...         |
| 3        | ...         |
| 3        | ...         |
| 3        | ...         |

如何获取每个人的 id 被拒绝和通过的次数?在同一个查询中它们出现在另一个查询中的次数是否可能?

| PersonId | Rejected | Passed | CountFromOtherTable
|----------|----------|--------| -----------------
| 1        | 2        | 2      | 3
| 2        | 1        | 1      | 2
| 3        | 4        | 1      | 3

只是 SQL 查询也不错,我可以尝试翻译它以与 typeorm 一起使用。

【问题讨论】:

  • 如果两张桌子有不同的人怎么办?

标签: sql postgresql join count typeorm


【解决方案1】:

通过使用 group by 条件聚合,您可以获得 Rejected 和 Passed 列,对于 CountFromOtherTable,您可以使用子查询。

select PersonId, sum (case when result='Rejected' then 1 else 0 end) Rejected ,
sum (case when result='Passed' then 1 else 0 end) Passed ,
(select count(*) from othertable o where o.personid=r.personid)CountFromOtherTable
from Results r
group by PersonId

DB-Fiddle:

架构和插入语句:

 create table Results ( PersonId int, Result   varchar(50));
 insert into Results values( 1,        'Rejected');
 insert into Results values( 1,        'Rejected');
 insert into Results values( 1,        'Passed');
 insert into Results values( 1,        'Passed');
 insert into Results values( 2,        'Rejected');
 insert into Results values( 2,        'Passed');
 insert into Results values( 3,        'Rejected');
 insert into Results values( 3,        'Rejected');
 insert into Results values( 3,        'Rejected');
 insert into Results values( 3,        'Rejected');
 insert into Results values( 3,        'Passed');
 
 create table OtherTable (PersonId int);
 insert into OtherTable values( 1 );
 insert into OtherTable values( 1 );
 insert into OtherTable values( 1 );
 insert into OtherTable values( 2 );
 insert into OtherTable values( 2 );
 insert into OtherTable values( 3 );
 insert into OtherTable values( 3 );
 insert into OtherTable values( 3 );
 insert into OtherTable values( 3 );

查询:

 select PersonId, sum (case when result='Rejected' then 1 else 0 end) Rejected ,
 sum (case when result='Passed' then 1 else 0 end) Passed ,
 (select count(*) from othertable o where o.personid=r.personid)CountFromOtherTable
 from Results r
 group by PersonId
 order by PersonId

输出:

personid rejected passed countfromothertable
1 2 2 3
2 1 1 2
3 4 1 4

dbhere

【讨论】:

    【解决方案2】:

    基本上,您需要条件聚合。在 Postgres 中,我建议为此使用 filterleft join

    select r.PersonId,
           count(*) filter (where r.result = 'Rejected') as Rejected,
           count(*) filter (where r.result = 'Passed') as Passed
           coalesce(o.cnt, 0) as other_table_cnt
    from Results r left join
         (select personid, count(*) as cnt
          from othertable o
          group by personid
         ) o
         using (personid)
    group by r.PersonId;
    

    注意:这假设您希望第一个表中的所有人,因此left join。如果您希望所有人都在 both 表中,请使用 inner join。如果您想要 either 表中的所有人,请使用 full join

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 2021-01-09
      相关资源
      最近更新 更多