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

Permintaan ltree Postgresql untuk menemukan induk dengan sebagian besar anak; tidak termasuk root

Solusi

Untuk menemukan simpul dengan anak paling banyak:

SELECT subpath(path, -1, 1), count(*) AS children
FROM   tbl
WHERE  path <> ''
GROUP  BY 1
ORDER  BY 2 DESC
LIMIT  1;

... dan mengecualikan node root:

SELECT *
FROM  (
   SELECT ltree2text(subpath(path, -1, 1))::int AS tbl_id, count(*) AS children
   FROM   tbl
   WHERE  path <> ''
   GROUP  BY 1
   ) ct
LEFT   JOIN (
   SELECT tbl_id
   FROM   tbl
   WHERE  path = ''
   ) x USING  (tbl_id)
WHERE  x.tbl_id IS NULL
ORDER  BY children DESC
LIMIT  1

Dengan asumsi bahwa node root memiliki ltree yang kosong ('' ) sebagai jalan. Mungkin NULL . Kemudian gunakan path IS NULL ...

Pemenang dalam contoh Anda sebenarnya adalah 2001 , dengan 5 anak.

-> SQLfiddle

Bagaimana?

  • Gunakan fungsi subpath(...) disediakan oleh modul tambahan ltree .

  • Dapatkan simpul terakhir di jalur dengan offset negatif , yang merupakan induk langsung dari elemen.

  • Hitung seberapa sering induk itu muncul, kecualikan simpul akar dan ambil yang tersisa dengan jumlah tertinggi.

  • Gunakan ltree2text() untuk mengekstrak nilai dari ltree .

  • Jika beberapa node memiliki anak paling banyak yang sama, maka yang dipilih adalah sembarang dalam contoh.

Kasus uji

Ini adalah pekerjaan yang harus saya lakukan untuk mendapatkan kasus uji yang berguna (setelah memangkas beberapa kebisingan):

Lihat SQLfiddle .

Dengan kata lain:harap ingat untuk memberikan kasus uji yang berguna lain kali.

Kolom tambahan

Jawaban untuk komentar.
Pertama, perluas kasus uji:

ALTER TABLE tbl ADD COLUMN postal_code text
              , ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;

Lihat:

SELECT * FROM tbl;

Cukup JOIN hasil ke induk di tabel dasar:

SELECT ct.*, t.postal_code
FROM  (
   SELECT ltree2text(subpath(path, -1, 1))::int AS tbl_id, count(*) AS children
   FROM   tbl
   WHERE  path <> ''
   GROUP  BY 1
   ) ct
LEFT   JOIN (
   SELECT tbl_id
   FROM   tbl
   WHERE  path = ''
   ) x USING  (tbl_id)
JOIN  tbl t USING (tbl_id)
WHERE  x.tbl_id IS NULL
ORDER  BY children DESC
LIMIT  1;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mengubah tipe data menjadi float dan membulatkan menjadi 2 digit desimal

  2. Cara menggunakan kursor sisi server dengan psycopg2

  3. Simulasikan CREATE DATABASE JIKA TIDAK ADA untuk PostgreSQL?

  4. Bagaimana membandingkan dua tabel di postgres

  5. kesalahan segmentasi pg.rb [Mojave upgrade]