我有这张桌子:
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 ------------------------- |schedule_id |date | |------------+------------| |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 | -----------------------------------
我想要一张这样的桌子:
characteristic --------------------------------------- |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
有没有更好的方法来执行此类查询? 我应该创建“州”列的索引吗?如果是这样,它应该怎么样?
答案 0 :(得分:4)
您想制作数据透视表。如果您事先知道所有可能的状态值,那么在SQL中创建一个的简单方法是使用sum
和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;
另一种方法是使用crosstab表函数。
这些都不会让你不知道状态值的集合(以及结果集中的列)。
答案 1 :(得分: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
;
答案 2 :(得分:0)
标准方法是使用带有CASE的SUM()和带有GROUP BY的JOIN:
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