如何以良好的性能查询多个COUNT(*)

New*_*ewK 2 sql postgresql relational-database postgresql-9.2

我有这张桌子:

CREATE TABLE schedule (
schedule_id serial NOT NULL,
start_date date,
CONSTRAINT schedule_id PRIMARY KEY (schedule_element_id)
)
Run Code Online (Sandbox Code Playgroud)

和这张桌子:

CREATE TABLE schedule_user (
schedule_user_id serial NOT NULL,
schedule_id integer,
state int,
CONSTRAINT fk_schedule_id   FOREIGN KEY (schedule_id)
      REFERENCES schedule (schedule_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
Run Code Online (Sandbox Code Playgroud)
时间表 
 -------------------------
| schedule_id |日期|
| ------------ + ------------ |
| 1 |'2013-10-10'|
| 2 |'2013-10-20'|
| 3 |'2013-08-13'|
 -------------------------

schedule_user 
 -----------------------------------
| schedule_user_id | schedule_id | state |
| ---------------- + ------------ + ----- |
| 1 | 1 | 0 |
| 2 | 1 | 1 |
| 3 | 1 | 2 |
| 4 | 1 | 0 |
| 5 | 1 | 1 |
| 6 | 1 | 1 |
| 4 | 2 | 0 |
| 5 | 2 | 1 |
| 7 | 2 | 0 |
| 2 | 3 | 1 |
 -----------------------------------

我想要一个这样的表:

特性
 ---------------------------------------
| schedule_id | state0 | state1 | state2 | total |
| ------------ + ------ + ------ + ------ + ----- |
| 1 | 2 | 3 | 1 | 6 |
| 2 | 2 | 1 | 0 | 3 |
| 3 | 1 | 1 | 0 | 2 |
 ---------------------------------------

我做了这个查询,看起来和它的性能一样可怕。

SELECT 
    schedule.schedule_id AS id, 
    (( SELECT count(*) AS count
         FROM schedule_user
         WHERE schedule_user.schedule_id = schedule.schedule_id
           AND state=0))::integer AS state0, 
    (( SELECT count(*) AS count
         FROM schedule_user
         WHERE schedule_user.schedule_id = schedule.schedule_id
           AND state=1))::integer AS state1,
    (( SELECT count(*) AS count
         FROM schedule_user
         WHERE schedule_user.schedule_id = schedule.schedule_id
           AND state=2))::integer AS state2,          
    (( SELECT count(*) AS count
         FROM schedule_user
         WHERE schedule_user.schedule_id = schedule.schedule_id))::integer
       AS total
  FROM schedule
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来执行这样的查询?我应该创建“状态”列的索引吗?如果是这样,它应该是什么样?

bab*_*unk 5

您要制作数据透视表。如果您事先知道state的所有可能值,那么在SQL中创建一个简单方法就是使用sumand case语句。

select schedule_id,
       sum(case state when 0 then 1 else 0 end) as state0,
       sum(case state when 1 then 1 else 0 end) as state1,
       sum(case state when 2 then 1 else 0 end) as state2,
       count(*) as total
from schedule_user
group by schedule_id;
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用交叉表表功能。

这些都不会让您不知道状态值集(因此也不知道结果集中的列)。