2014-03-29 40 views
0

這裏是我的問題 檢索 至少有三個預訂(不包括那些取消)的每種服務的預訂總數。 即其中狀態='打開'和'完成'SQL COUNT EXCLUDE

我不確定如何排除和如何計算列中的值?

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) 
); 
+0

張貼表格的結構。 '\ d booking' –

回答

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的。

這將是更清潔和更有效地使用用於status列的enum數據類型而不是VARCHAR(9)。那麼你也不需要約束CHECK約束。

對於這個特定查詢的最佳性能,你可以有一個partial covering index(這也從enum數據類型利潤):

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

各項指標進行維護的成本,所以只有保持這種量身定製的指數,如果它實際上會使您的查詢更快(使用EXPLAIN ANALYZE進行測試),並且它經常運行和/或重要。

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

@TheGuy請檢查Erwin的答案。他只是將他的查詢中唯一的主要區別從'left'改爲'inner'加入。 –

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子句的作用。