PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Jumlah pesanan pengulangan / duplikat berturut-turut

Kasus uji

Pertama, cara yang lebih berguna untuk menyajikan data Anda - atau bahkan lebih baik, dalam sqlfiddle , siap bermain dengan:

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

Kueri yang disederhanakan

Karena masih belum jelas, saya hanya mengasumsikan hal di atas seperti yang diberikan.
Selanjutnya, saya menyederhanakan kueri Anda untuk sampai pada:

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;

Sekarang, meskipun semuanya bagus dan berkilau untuk menggunakan SQL murni, ini akan menjadi banyak lebih cepat dengan fungsi plpgsql, karena dapat melakukannya dalam satu pemindaian tabel di mana kueri ini membutuhkan setidaknya tiga pemindaian.

Lebih cepat dengan fungsi 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$;

Telepon:

SELECT * FROM x.f_repeat_ct();

Pastikan untuk mengkualifikasi tabel nama kolom Anda setiap saat dalam fungsi plpgsql semacam ini, karena kami menggunakan nama yang sama sebagai parameter keluaran yang akan didahulukan jika tidak memenuhi syarat.

Milyaran baris

Jika Anda memiliki miliar baris , Anda mungkin ingin membagi operasi ini. Saya mengutip manualnya di sini:

Catatan:Implementasi RETURN NEXT saat ini dan RETURN QUERY menyimpan seluruh hasil yang ditetapkan sebelum kembali dari fungsi, seperti yang dibahas di atas. Itu berarti bahwa jika fungsi PL/pgSQL menghasilkan kumpulan hasil yang sangat besar, kinerjanya mungkin buruk:data akan ditulis ke disk untuk menghindari kehabisan memori, tetapi fungsi itu sendiri tidak akan kembali sampai seluruh kumpulan hasil dihasilkan. Versi PL/pgSQL yang akan datang mungkin memungkinkan pengguna untuk menentukan fungsi pengembalian-set yang tidak memiliki batasan ini. Saat ini, titik di mana data mulai ditulis ke disk dikendalikan oleh variabel work_memconfiguration. Administrator yang memiliki memori yang cukup untuk menyimpan kumpulan hasil yang lebih besar dalam memori harus mempertimbangkan untuk meningkatkan parameter ini.

Pertimbangkan untuk menghitung baris untuk satu sistem pada satu waktu atau tetapkan nilai yang cukup tinggi untuk work_mem untuk mengatasi beban. Ikuti tautan yang disediakan dalam kutipan tentang lebih lanjut tentang work_mem.

Salah satu caranya adalah dengan menetapkan nilai yang sangat tinggi untuk work_mem dengan SET LOCAL di fungsi Anda, yang hanya berlaku untuk untuk transaksi saat ini. Saya menambahkan baris komentar di function. Jangan jangan atur sangat tinggi secara global, karena ini dapat mematikan server Anda. Baca manualnya.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Panduan untuk PGpool - Petunjuk &Pengamatan:Bagian Tiga

  2. postgreSQL - dalam vs apa pun

  3. Menyebarkan Django + Python 3 + PostgreSQL ke AWS Elastic Beanstalk

  4. Inti Kerangka Entitas - Berisi apakah peka huruf besar-kecil atau tidak peka huruf besar-kecil?

  5. Mengonversi kueri SELECT DISTINCT ON dari Postgresql ke MySQL