PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Tổng hợp các bản ghi đã tham gia gần đây nhất mỗi tuần

Bạn cần một mục dữ liệu mỗi tuần và mục tiêu (trước khi tổng hợp số lượng cho mỗi công ty). Đó là CROSS JOIN đơn giản giữa generate_series()goals . Phần đắt (có thể) là để có được state hiện tại từ updates cho mỗi. Giống như @Paul đã được đề xuất , một LATERAL tham gia có vẻ như là công cụ tốt nhất. Chỉ thực hiện cho các bản cập nhật updates tuy nhiên, và sử dụng kỹ thuật nhanh hơn với LIMIT 1 .

Và đơn giản hóa việc xử lý ngày tháng với date_trunc() .

SELECT w_start
     , g.company_id
     , count(*) FILTER (WHERE u.status = 'green') AS green_count
     , count(*) FILTER (WHERE u.status = 'amber') AS amber_count
     , count(*) FILTER (WHERE u.status = 'red')   AS red_count
FROM   generate_series(date_trunc('week', NOW() - interval '2 months')
                     , date_trunc('week', NOW())
                     , interval '1 week') w_start
CROSS  JOIN goals g
LEFT   JOIN LATERAL (
   SELECT status
   FROM   updates
   WHERE  goal_id = g.id
   AND    created_at < w_start
   ORDER  BY created_at DESC
   LIMIT  1
   ) u ON true
GROUP  BY w_start, g.company_id
ORDER  BY w_start, g.company_id;

Để thực hiện điều này nhanh chóng bạn cần một chỉ mục nhiều cột :

CREATE INDEX updates_special_idx ON updates (goal_id, created_at DESC, status);

Thứ tự giảm dần cho created_at là tốt nhất, nhưng không hoàn toàn cần thiết. Postgres có thể quét ngược các chỉ mục gần như chính xác nhanh chóng. ( Tuy nhiên, không áp dụng cho thứ tự sắp xếp ngược của nhiều cột. )

Lập chỉ mục các cột trong that gọi món. Tại sao?

Và cột thứ ba state chỉ được thêm vào để cho phép nhanh chóng quét chỉ chỉ mục về các bản cập nhật updates . Trường hợp liên quan:

1 nghìn mục tiêu trong 9 tuần (khoảng thời gian 2 tháng của bạn trùng lặp với ít nhất 9 tuần) chỉ yêu cầu 9 nghìn lần tra cứu chỉ mục cho bảng thứ 2 chỉ 1 nghìn hàng. Đối với những chiếc bàn nhỏ như thế này, hiệu suất không phải là vấn đề nhiều. Nhưng khi bạn có thêm vài nghìn bảng trong mỗi bảng, hiệu suất sẽ kém đi khi quét tuần tự.

w_start đại diện cho sự bắt đầu của mỗi tuần. Do đó, số đếm được dành cho đầu tuần. Bạn có thể vẫn trích xuất năm và tuần (hoặc bất kỳ chi tiết nào khác đại diện cho tuần của bạn), nếu bạn nhấn mạnh:

   EXTRACT(isoyear from w_start) AS year
 , EXTRACT(week    from w_start) AS week

Tốt nhất với ISOYEAR , như @Paul đã giải thích.

SQL Fiddle.

Có liên quan:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để đối sánh biểu thức chính quy trên một cột cho PostgreSQL trong EF Core?

  2. Giúp Quản lý Cơ sở dữ liệu Sản xuất PostgreSQL dễ dàng hơn

  3. Nhận các giá trị mặc định của các cột trong bảng trong Postgres?

  4. Cách gỡ lỗi:Lỗi nội bộ giao dịch hiện tại bị hủy bỏ, các lệnh bị bỏ qua cho đến khi kết thúc khối giao dịch

  5. Có thể thay thế proxy Cloud SQL bằng proxy Istio không?