Là sử dụng SUM () hai lần tối ưu?


8

Tôi biết tôi phải viết SUMhai lần, nếu tôi muốn sử dụng nó trong một HAVINGmệnh đề (hoặc sử dụng bảng dẫn xuất khác):

SELECT  id,
  sum(hours) AS totalhours
  FROM mytable
  GROUP BY id
  HAVING sum(hours) > 50;

Câu hỏi của tôi bây giờ là, liệu điều này có tối ưu hay không. Là một lập trình viên, truy vấn này trông giống như DB sẽ tính tổng hai lần. Có phải vậy không, hay tôi nên dựa vào việc tối ưu hóa công cụ DB sẽ làm cho tôi?

Cập nhật: giải thích về một truy vấn có thể so sánh:

postgres=> explain select sum(counttodo) from orderline group by orderlineid having sum(counttodo) > 100;
                             QUERY PLAN                             
--------------------------------------------------------------------
 HashAggregate  (cost=1.31..1.54 rows=18 width=8)
   Filter: (sum(counttodo) > 100)
   ->  Seq Scan on orderline  (cost=0.00..1.18 rows=18 width=8)
(3 rows)

bạn có thể gửi lời giải thích?
Ste

Tôi sẽ không trả lời điều này vì có một lời giải thích ngắn gọn, súc tích ở đây : "Trong trường hợp bạn đang tự hỏi tại sao bạn không thể tham khảo các bí danh CHỌN sau này trong truy vấn, như trong mệnh đề WHERE, tất cả phải làm theo thứ tự Đánh giá. SQL không được đánh giá theo thứ tự được viết. Danh sách CHỌN thực sự được đánh giá gần như cuối cùng và nội dung của nó vẫn chưa tồn tại khi HAVING v.v ... được xử lý. Điều này trở nên quan trọng khi danh sách chọn bao gồm các hàm với tác dụng phụ [...] "
dezso

... đây là lý do tại sao bạn không thể chỉ tham chiếu cột tổng hợp trong HAVINGmệnh đề - nhưng, theo hiểu biết của tôi, bên trong điều này được thực hiện theo cách khác.
dezso

2
@BartFriederichs tốt, nhiều người phàn nàn dọc theo những dòng này (tôi cũng đã phàn nàn cho đến khi tôi không quen với nó ...) Nó không được thực hiện hai lần và có thể được thực hiện bằng cách sử dụng bí danh HAVING(và sau đó kéo định nghĩa cột từ SELECTmệnh đề) - vì một số lý do họ không làm điều đó.
dezso

3
Tôi nghĩ rằng để cho công cụ DB lo lắng về việc tối ưu hóa phải là bản chất thứ hai đối với một học viên RDBMS. SQL là 4GL, vì vậy chúng tôi xác định tập kết quả mà chúng tôi muốn, không phải là phương tiện đạt được. Có nhiều vấn đề khác ngoài kia mà chúng tôi không lo lắng trong hầu hết các phần - tham gia hoặc chuyển đổi EXISTS thành tham gia chẳng hạn. Vấn đề đặc biệt này là một vấn đề từ quan điểm "Đừng lặp lại chính mình" đối với biểu hiện phức tạp, nhưng cách giải quyết hợp lý (chế độ xem nội tuyến, CTE) có thể giúp ích cho những vấn đề đó.
David Aldridge

Câu trả lời:


3

Tổng chỉ được tính một lần.

Tôi đã xác minh điều này bằng cách sử dụng

create table mytable (id int, hours int);
insert into mytable values (1, 60);
select sum(hours) from mytable group by id having sum(hours) > 50;

và sau đó sử dụng trình gỡ lỗi để kiểm tra số lần int4_sum(hàm chuyển đổi phía sau sumtổng hợp) được gọi là: một lần.


0

So sánh truy vấn của bạn

explain
select sum(counttodo)
from orderline
group by orderlineid
having sum(counttodo) > 100

Để tương đương với một kiểm tra xem chúng khác nhau như thế nào

explain
select *
from (
    select sum(counttodo) counttodo
    from orderline
    group by orderlineid
) s
where counttodo > 100

1
Tôi có thể thấy những gì bạn đang nhận được nhưng ở dạng hiện tại, điều này không tạo ra câu trả lời "tốt". Gửi lời giải thích cho mỗi người với một ít bình luận hơn và bạn tốt cho một số upvote.
Mark Storey-Smith

0

Bạn không phải viết SUMhai lần nếu bạn không cần lấy nó; nếu bạn chỉ quan tâm đến việc idcó một SUM(hours) > 50thì điều sau đây là hoàn toàn hợp lệ:

SELECT id,
FROM mytable
GROUP BY id
HAVING sum(hours) > 50;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.