PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

डेटाबेस में बहुआयामी सरणी स्टोर करें:संबंधपरक या बहुआयामी?

यदि आपको बस इतना ही चाहिए, तो आप LIKE खोज का उपयोग कर सकते हैं

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

CELL . से शुरू होने वाले इंडेक्स के साथ यह एक रेंज चेक है, जो तेज है।

यदि आपका डेटा ऐसा नहीं दिखता है, तो आप एक path बना सकते हैं कॉलम जो एक निर्देशिका पथ की तरह दिखता है और इसमें जड़ से तत्व तक "रास्ते/पथ पर" सभी नोड होते हैं।

| 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/ |

'AE' (स्वयं सहित) के सभी वंशजों को पुनः प्राप्त करने के लिए आपकी क्वेरी होगी

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

या (MySQL विशिष्ट संयोजन)

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

परिणाम:

| 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/ |

डेमो

प्रदर्शन

मैंने MariaDB पर नकली डेटा की 100K पंक्तियां बनाई हैं अनुक्रम प्लग इन के साथ निम्नलिखित स्क्रिप्ट का उपयोग करना:

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.

परीक्षा

सभी तत्वों को रूट के अंतर्गत गिनें:

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

एक विशिष्ट नोड के तहत सबट्री तत्व प्राप्त करें:

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

परिणाम:

| 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

यह PostgreSQL के लिए भी काम करता है। केवल स्ट्रिंग कॉन्सटेनेशन सिंटैक्स को बदलना होगा:

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

डेमो: sqlfiddle - rextester

खोज कैसे काम करती है

यदि आप परीक्षण के उदाहरण को देखें, तो आप देखेंगे कि परिणाम में सभी पथ '1/4/11/14/614/4284/' से शुरू होते हैं। यह CELL='3B0' . के साथ सबट्री रूट का पथ है . अगर path कॉलम को अनुक्रमित किया गया है, इंजन उन सभी को कुशलता से ढूंढ लेगा, क्योंकि सूचकांक को path . द्वारा क्रमबद्ध किया गया है . यह ऐसा है जैसे आप 'पोल' से शुरू होने वाले सभी शब्दों को 100K शब्दों के शब्दकोश में खोजना चाहेंगे। आपको पूरा शब्दकोश पढ़ने की आवश्यकता नहीं होगी।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. उन मूल्यों के लिए क्वेरी कैसे करें जिनके पास पोस्टग्रेएसक्यूएल में सबसे ज्यादा वोट गिनती है और कोई झंडे नहीं हैं?

  2. उत्पन्न कॉलम के साथ PostgreSQL क्वेरी

  3. कैसे जांचें कि PostgreSQL सार्वजनिक स्कीमा मौजूद है या नहीं?

  4. मैं तालिकाओं के बीच अंतर को कैसे तेज कर सकता हूं?

  5. PostgreSQL RDS dblink_connect () का उपयोग करते समय कनेक्शन पासवर्ड की हार्ड कोडिंग से बचें