PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Postgresql ltree заявка за намиране на родител с повечето деца; с изключение на корена

Решение

За да намерите възела с най-много деца:

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

... и изключете основните възли:

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

Ако приемем, че основните възли имат празно ltree ('' ) като път. Може да е NULL . След това използвайте path IS NULL ...

Победителят във вашия пример всъщност е 2001 , с 5 деца.

-> SQLfiddle

Как?

  • Използвайте функцията subpath(...) предоставено от допълнителния модул ltree .

  • Вземете последния възел в пътя с отрицателно отместване , който е пряк родител на елемента.

  • Пребройте колко често се появява този родител, изключете основните възли и вземете оставащия с най-голям брой.

  • Използвайте ltree2text() за да извлечете стойността от ltree .

  • Ако множество възли имат еднакво най-много деца, в примера се избира произволен.

Тестов случай

Това е работата, която трябваше да свърша, за да стигна до полезен тестов случай (след отстраняване на малко шум):

Вижте SQLfiddle .

С други думи:моля, не забравяйте да предоставите полезен тестов случай следващия път.

Допълнителни колони

Отговорете на коментар.
Първо разгънете тестовия случай:

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

Разгледайте:

SELECT * FROM tbl;

Просто JOIN резултат на родителя в основната таблица:

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. Как да използвате SQLAlchemy за безпроблемен достъп до множество бази данни?

  2. Как да конвертирам numpy NaN обекти в SQL нули?

  3. postgresql distinct не работи

  4. Мога ли да „прекомпилирам“ таблица, връщаща функции, след като тази таблица е ALTER-ed по време на миграцията на база данни?

  5. Заявката не попада в индекса - това ли са правилните колони за индексиране?