2

我有这张桌子:

CREATE TABLE schedule (
schedule_id serial NOT NULL,
start_date date,
CONSTRAINT schedule_id PRIMARY KEY (schedule_element_id)
)

而这张表:

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
)
日程
 -------------------------
|schedule_id |日期 |
|------------+------------|
|1 |'2013-10-10'|
|2 |'2013-10-20'|
|3 |'2013-08-13'|
 -------------------------

schedule_user
 ----------------------------------
|schedule_user_id|schedule_id |状态|
|----------------+------------+-----|
|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

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

4

3 回答 3

6

你想做一个数据透视表。如果您事先知道所有可能的状态值,那么在 SQL 中创建一个简单的方法是使用sumcase语句。

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;

另一种方法是使用交叉表函数。

这些都不会让你不知道状态值的集合(以及结果集中的列)。

于 2013-03-21T18:27:26.873 回答
3

我会尝试

SELECT s.schedule_id,
       COUNT(CASE WHEN su.state = 0 THEN 1 END) AS state0,
       COUNT(CASE WHEN su.state = 1 THEN 1 END) AS state1,
       COUNT(CASE WHEN su.state = 2 THEN 1 END) AS state2,
       COUNT(su.state) AS total
  FROM schedule s
  LEFT
 OUTER
  JOIN schedule_user su
    ON su.schedule_id = s.schedule_id
 GROUP
    BY s.schedule_id
;
于 2013-03-21T18:25:10.460 回答
0

标准方法是使用 SUM() 和 CASE,而不是 JOIN 和 GROUP BY:

SELECT 
schedule.schedule_id AS id, 
SUM (case when state=0 then 1 else 0 end) AS state0, 
SUM (case when state=1 then 1 else 0 end) AS state1, 
SUM (case when state=2 then 1 else 0 end) AS state2, 
count(*) AS total
FROM schedule
LEFT JOIN schedule_user
  ON schedule_user.schedule_id = schedule.schedule_id
GROUP BY 1
于 2013-03-21T18:28:18.750 回答