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

Simpan array multidimensi dalam database:relasional atau multidimensi?

Jika hanya itu yang Anda butuhkan, Anda dapat menggunakan pencarian LIKE

SELECT *
FROM Table1
WHERE CELL LIKE 'AEE%';

Dengan indeks yang dimulai dengan CELL ini adalah pemeriksaan jangkauan, yang cepat.

Jika data Anda tidak terlihat seperti itu, Anda dapat membuat path kolom yang terlihat seperti jalur direktori dan berisi semua simpul "di jalan/jalur" dari root ke elemen.

| id | CELL | parent_id | path     |
|====|======|===========|==========|
|  1 | A    |      NULL | 1/       |
|  2 | AA   |         1 | 1/2/     |
|  3 | AAA  |         2 | 1/2/3/   |
|  4 | AAC  |         2 | 1/2/4/   |
|  5 | AB   |         1 | 1/5/     |
|  6 | AE   |         1 | 1/6/     | 
|  7 | AEA  |         6 | 1/6/7/   |
|  8 | AEE  |         6 | 1/6/8/   |
|  9 | AEEB |         8 | 1/6/8/9/ |

Untuk mengambil semua turunan 'AE' (termasuk dirinya sendiri), kueri Anda adalah

SELECT *
FROM tree t
WHERE path LIKE '1/6/%';

atau (gabungan khusus MySQL)

SELECT t.*
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = 'AE'
  AND t.path LIKE CONCAT(r.path, '%');

Hasil:

| id | CELL | parent_id |     path |
|====|======|===========|==========|
|  6 | AE   |         1 | 1/6/     |
|  7 | AEA  |         6 | 1/6/7/   |
|  8 | AEE  |         6 | 1/6/8/   |
|  9 | AEEB |         8 | 1/6/8/9/ |

Demo

Kinerja

Saya telah membuat 100 ribu baris data palsu di MariaDB dengan plugin urutan menggunakan skrip berikut:

drop table if exists tree;
CREATE TABLE tree (
  `id` int primary key,
  `CELL` varchar(50),
  `parent_id` int,
  `path` varchar(255),
  unique index (`CELL`),
  unique index (`path`)
);

DROP TRIGGER IF EXISTS `tree_after_insert`;
DELIMITER //
CREATE TRIGGER `tree_after_insert` BEFORE INSERT ON `tree` FOR EACH ROW BEGIN
    if new.id = 1 then
        set new.path := '1/';
    else    
        set new.path := concat((
            select path from tree where id = new.parent_id
        ), new.id, '/');
    end if;
END//
DELIMITER ;

insert into tree
    select seq as id
        , conv(seq, 10, 36) as CELL
        , case 
            when seq = 1 then null
            else floor(rand(1) * (seq-1)) + 1 
        end as parent_id
        , null as path
    from seq_1_to_100000
;
DROP TRIGGER IF EXISTS `tree_after_insert`;
-- runtime ~ 4 sec.

Tes

Hitung semua elemen di bawah root:

SELECT count(*)
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = '1'
  AND t.path LIKE CONCAT(r.path, '%');
-- result: 100000
-- runtime: ~ 30 ms

Dapatkan elemen subpohon di bawah simpul tertentu:

SELECT t.*
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = '3B0'
  AND t.path LIKE CONCAT(r.path, '%');
-- runtime: ~ 30 ms

Hasil:

| id    | CELL | parent_id | path                                |
|=======|======|===========|=====================================|
|  4284 | 3B0  |       614 | 1/4/11/14/614/4284/                 |
|  6560 | 528  |      4284 | 1/4/11/14/614/4284/6560/            |
|  8054 | 67Q  |      6560 | 1/4/11/14/614/4284/6560/8054/       |
| 14358 | B2U  |      6560 | 1/4/11/14/614/4284/6560/14358/      |
| 51911 | 141Z |      4284 | 1/4/11/14/614/4284/51911/           |
| 55695 | 16Z3 |      4284 | 1/4/11/14/614/4284/55695/           |
| 80172 | 1PV0 |      8054 | 1/4/11/14/614/4284/6560/8054/80172/ |
| 87101 | 1V7H |     51911 | 1/4/11/14/614/4284/51911/87101/     |

PostgreSQL

Ini juga berfungsi untuk PostgreSQL. Hanya sintaks rangkaian string yang harus diubah:

SELECT t.*
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = 'AE'
  AND t.path LIKE r.path || '%';

Demo: sqlfiddle - rextester

Bagaimana cara kerja pencarian

Jika Anda melihat contoh pengujian, Anda akan melihat bahwa semua jalur dalam hasil dimulai dengan '1/4/11/14/614/4284/'. Itu adalah path dari subtree root dengan CELL='3B0' . Jika path kolom diindeks, mesin akan menemukan semuanya secara efisien, karena indeks diurutkan berdasarkan path . Sepertinya Anda ingin menemukan semua kata yang dimulai dengan 'pol' dalam kamus dengan 100 ribu kata. Anda tidak perlu membaca seluruh kamus.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kesalahan saat memetakan array postgres di Spring JPA

  2. POSTGRES SALIN DARI PROGRAM ke tabel dinamis dengan kolom yang tidak diketahui

  3. Melakukan transaksi saat menjalankan Fungsi postgreql

  4. apa urutan pelarian untuk tanda hubung (-) di PostgreSQL

  5. Bagaimana cara mengubah pemilik database PostgreSql?