câu trả lời Sebas' Justin và có thể được mở rộng với một LEFT JOIN để loại bỏ 'khoảng trống', mà là thường mong muốn.
Nếu đó là không cần thiết, như một sự thay thế, chúng ta có thể đi học cũ Oracle NGÀY số học ...
SELECT TRUNC(t.time)+FLOOR(TO_CHAR(t.time,'sssss')/300)*300/86400 AS time
, AVG(t.value) AS avg_value
FROM foo t
WHERE t.time IS NOT NULL
GROUP BY TRUNC(t.time)+FLOOR(TO_CHAR(t.time,'sssss')/300)*300/86400
ORDER BY TRUNC(t.time)+FLOOR(TO_CHAR(t.time,'sssss')/300)*300/86400
Hãy giải nén một chút. Chúng ta có thể tách các thành phần ngày và giờ, sử dụng TRUNC để lấy phần ngày tháng và sử dụng TO_CHAR để trả về số giây kể từ nửa đêm. Chúng tôi biết 5 phút là 300 giây và chúng tôi biết có 86400 giây trong một ngày. Vì vậy, chúng ta có thể chia số giây cho 300, và lấy FLOOR (chỉ là phần nguyên), làm tròn chúng ta xuống ranh giới 5 phút gần nhất. Chúng ta nhân số đó lại (bằng 300), để lấy lại giây, và sau đó chia số giây đó trong một ngày (86400), và chúng ta có thể thêm nó vào phần ngày tháng (cắt ngắn).
Đau đớn, vâng. Nhưng nhanh quá.
LƯU Ý: điều này trả về giá trị thời gian làm tròn là DATE
, điều này có thể được đưa trở lại dấu thời gian nếu cần, nhưng đối với ranh giới thậm chí 5 phút, DATE
có đủ độ phân giải.
Là một lợi ích của phương pháp này, cho một bảng lớn, chúng ta có thể tăng hiệu suất của truy vấn bằng cách thêm một chỉ số bao phủ cho truy vấn này:
CREATE INDEX foo_FBX1
ON foo (TRUNC(t.time)+FLOOR(TO_CHAR(t.time,'sssss')/300)*300/86400,value);
PHỤ LỤC:
MiMo cung cấp câu trả lời cho SQL Server, cho thấy rằng nó có thể thích ứng với Oracle. Đây là một sự thích nghi của cách tiếp cận đó trong Oracle. Lưu ý rằng Oracle không cung cấp các hàm tương đương cho các hàm DATEDIFF và DATEADD. Oracle sử dụng số học đơn giản để thay thế.
SELECT TO_DATE('00010101','YYYYMMDD')+FLOOR((t.time-TO_DATE('00010101','YYYYMMDD'))*288)/288
AS time
, AVG(t.value) AS avg_value
FROM foo t
WHERE t.time IS NOT NULL
GROUP BY TO_DATE('00010101','YYYYMMDD')+FLOOR((t.time-TO_DATE('00010101','YYYYMMDD'))*288)/288
ORDER BY TO_DATE('00010101','YYYYMMDD')+FLOOR((t.time-TO_DATE('00010101','YYYYMMDD'))*288)/288
Sự lựa chọn của Jan 1, 0001 AD là một ngày cơ sở là tùy ý, nhưng tôi không muốn gây rối với các giá trị âm, và tìm hiểu xem SÀN sẽ là đúng, hay là chúng ta sẽ cần phải sử dụng CEIL với số âm. (Số ma thuật 288 là kết quả của 1440 phút trong một ngày chia cho 5). Trong trường hợp này, chúng tôi đang lấy ngày phân số, nhân với 1440 và chia cho 5, và lấy phần nguyên của nó, và sau đó đưa nó trở lại ngày phân số. Nó là hấp dẫn để kéo "cơ sở ngày" từ một gói PL/SQL, hoặc nhận được nó từ một truy vấn phụ, nhưng làm một trong những người có thể ngăn chặn biểu thức này được xác định. Và chúng tôi thực sự muốn tiếp tục mở tùy chọn tạo chỉ mục dựa trên chức năng.
Tùy chọn của tôi là để tránh nhu cầu bao gồm "ngày cơ sở" trong tính toán.
Phiên bản Oracle 10g +? – Sebas
Có, xin lỗi - 10g – Nick