SQL COUNT EXCLUDE

时间:2014-03-29 11:39:16

标签: sql postgresql join count aggregate-functions

您好,我的问题 检索每种类型服务的预订总数 至少有三次预订(不包括已取消的预订)。 即状态='打开' AND'完成'

我不确定如何排除以及如何计算列中的值?

SELECT Service.type, Service.description,   
COUNT (DISTINCT status) 
FROM Booking
LEFT JOIN Service
ON Booking.service = Service.type
WHERE status >= 3
EXCLUDE 'cancelled'
GROUP BY status DESC;

CREATE TABLE Booking(
car         CHAR(8)                             ,
on_date     DATE                        NOT NULL,
at_time     TIME                        NOT NULL,
technician  CHAR(6)                     NOT NULL,
service     VARCHAR(15)                 NOT NULL,
status      VARCHAR(9)CHECK(status IN ('open','done', 'cancelled')) DEFAULT 'open'     NOT         NULL, 
note        VARCHAR(200)                            ,
rating      INTEGER CHECK(rating IN('0','1','2','3','4','5')) DEFAULT '0'   NOT NULL,
feedback    VARCHAR(2048)                           ,

PRIMARY KEY (car, on_date, at_time),

FOREIGN KEY (car) REFERENCES Car (cid)
                ON DELETE CASCADE   
                ON UPDATE CASCADE, 

FOREIGN KEY (technician) REFERENCES Technician (tech_id)
                ON DELETE CASCADE   
                ON UPDATE CASCADE, 

FOREIGN KEY (service) REFERENCES Service (type)
                ON DELETE CASCADE   
                ON UPDATE CASCADE
);

CREATE TABLE Service(
type        VARCHAR(15)     PRIMARY KEY,
description VARCHAR(2048)   
);

3 个答案:

答案 0 :(得分:0)

select s.type, s.description, count(*) 
from
    booking b
    inner join
    service s on b.service = s.type
where status != 'cancelled'
group by 1, 2
having count(*) >= 3
order by 3 desc;

答案 1 :(得分:0)

怎么样:

SELECT Service.type, Service.description, COUNT (status) 
FROM Booking 
LEFT JOIN Service ON Booking.service = Service.type 
WHERE status != 'cancelled' 
GROUP BY Service.type, Service.description
HAVING COUNT(status) >= 2;

服务属性也必须进行分组。 聚合过滤(COUNT(status)HAVING子句的作用。

答案 2 :(得分:0)

首先聚合并稍后加入会更快。加入操作较少。因此子查询:

SELECT s.type, s.description, b.ct
FROM  (
   SELECT service, count(*) AS ct
   FROM   booking
   WHERE  status <> 'cancelled'
   GROUP  BY 1
   HAVING count(*) > 2
   ) b
JOIN service s ON s.type = b.service;

由于您使用外键约束强制引用完整性并且service已定义为NOT NULL,因此您也可以使用[INNER] JOIN而不是LEFT [OUTER] JOIN 查询

VARCHAR(9)列使用enum数据类型而不是status会更清晰,更有效。那么你也不需要CHECK约束。

为了获得此特定查询的最佳效果,您可以拥有partial covering index(也可以从enum数据类型中获利):

CREATE INDEX foo ON booking (service)
WHERE  status <> 'cancelled';

每个索引都有一个维护成本,所以只有保留这个量身定制的索引,如果它实际上使您的查询更快(使用EXPLAIN ANALYZE进行测试)并且它经常运行和/或很重要。