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

Số lần lặp lại / trùng lặp có thứ tự

Trường hợp thử nghiệm

Đầu tiên, một cách hữu ích hơn để trình bày dữ liệu của bạn - hoặc thậm chí tốt hơn, trong sqlfiddle , sẵn sàng chơi với:

CREATE TEMP TABLE data(
   system_measured int
 , time_of_measurement int
 , measurement int
);

INSERT INTO data VALUES
 (1, 1, 5)
,(1, 2, 150)
,(1, 3, 5)
,(1, 4, 5)
,(2, 1, 5)
,(2, 2, 5)
,(2, 3, 5)
,(2, 4, 5)
,(2, 5, 150)
,(2, 6, 5)
,(2, 7, 5)
,(2, 8, 5);

Truy vấn đơn giản hóa

Vì nó vẫn chưa rõ ràng, tôi chỉ giả định ở trên như đã cho.
Tiếp theo, tôi đã đơn giản hóa truy vấn của bạn để đến:

WITH x AS (
   SELECT *, CASE WHEN lag(measurement) OVER (PARTITION BY system_measured
                               ORDER BY time_of_measurement) = measurement
                  THEN 0 ELSE 1 END AS step
   FROM   data
   )
   , y AS (
   SELECT *, sum(step) OVER(PARTITION BY system_measured
                            ORDER BY time_of_measurement) AS grp
   FROM   x
   )
SELECT * ,row_number() OVER (PARTITION BY system_measured, grp
                             ORDER BY time_of_measurement) - 1 AS repeat_ct
FROM   y
ORDER  BY system_measured, time_of_measurement;

Bây giờ, mặc dù sử dụng SQL thuần túy là rất tốt và sáng bóng, nhưng điều này sẽ nhiều nhanh hơn với hàm plpgsql, bởi vì nó có thể thực hiện việc đó trong một lần quét bảng trong đó truy vấn này cần ít nhất ba lần quét.

Nhanh hơn với hàm plpgsql:

CREATE OR REPLACE FUNCTION x.f_repeat_ct()
  RETURNS TABLE (
    system_measured int
  , time_of_measurement int
  , measurement int, repeat_ct int
  )  LANGUAGE plpgsql AS
$func$
DECLARE
   r    data;     -- table name serves as record type
   r0   data;
BEGIN

-- SET LOCAL work_mem = '1000 MB';  -- uncomment an adapt if needed, see below!

repeat_ct := 0;   -- init

FOR r IN
   SELECT * FROM data d ORDER BY d.system_measured, d.time_of_measurement
LOOP
   IF  r.system_measured = r0.system_measured
       AND r.measurement = r0.measurement THEN
      repeat_ct := repeat_ct + 1;   -- start new array
   ELSE
      repeat_ct := 0;               -- start new count
   END IF;

   RETURN QUERY SELECT r.*, repeat_ct;

   r0 := r;                         -- remember last row
END LOOP;

END
$func$;

Gọi:

SELECT * FROM x.f_repeat_ct();

Hãy đảm bảo luôn đủ điều kiện cho bảng tên cột của bạn trong loại hàm plpgsql này, vì chúng tôi sử dụng các tên giống như các tham số đầu ra sẽ được ưu tiên hơn nếu không đủ điều kiện.

Hàng tỷ hàng

Nếu bạn có hàng tỷ hàng , bạn có thể muốn chia nhỏ hoạt động này. Tôi trích dẫn sách hướng dẫn ở đây:

Lưu ý:Việc triển khai RETURN NEXT hiện tại và RETURN QUERY lưu trữ toàn bộ tập kết quả trước khi trả về từ hàm, như đã đề cập ở trên. Điều đó có nghĩa là nếu một hàm PL / pgSQL tạo ra một tập kết quả rất lớn, hiệu suất có thể kém:dữ liệu sẽ được ghi vào đĩa để tránh cạn bộ nhớ, nhưng bản thân hàm sẽ không quay trở lại cho đến khi toàn bộ tập kết quả được tạo. Phiên bản tương lai của PL / pgSQL có thể cho phép người dùng xác định các hàm set-return không có giới hạn này. Hiện tại, điểm mà dữ liệu bắt đầu được ghi vào đĩa được điều khiển bởi biến work_memconfiguration. Quản trị viên có đủ bộ nhớ để lưu trữ các tập kết quả lớn hơn trong bộ nhớ nên xem xét việc tăng thông số này.

Cân nhắc tính toán các hàng cho một hệ thống tại một thời điểm hoặc đặt giá trị đủ cao cho work_mem để đối phó với tải. Theo liên kết được cung cấp trong phần trích dẫn để biết thêm về work_mem.

Có một cách là đặt giá trị rất cao cho work_mem với SET LOCAL trong chức năng của bạn, điều này chỉ hiệu quả cho giao dịch hiện tại. Tôi đã thêm một dòng nhận xét trong hàm. Đừng không đặt nó rất cao trên toàn cầu, vì điều này có thể làm hỏng máy chủ của bạn. Đọc hướng dẫn.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Không tìm thấy hàm chuyển đổi từ không xác định thành văn bản

  2. Kế hoạch Cửa hàng Cột

  3. Bảng postgresql tồn tại, nhưng mối quan hệ nhận được không tồn tại khi truy vấn

  4. heroku, postgreSQL, django, comments, Deliciousypie:Không có toán tử nào phù hợp với (các) loại đối số và tên đã cho. Bạn có thể cần thêm phôi loại rõ ràng

  5. Hướng dẫn về Pgpool cho PostgreSQL:Phần thứ hai