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

क्या मैं इसे शुद्ध MySQL के साथ हल कर सकता हूं? ('' कॉलम में अलग किए गए मानों से जुड़ना)

अगर user_resources (t1) प्रत्येक user => resource . के लिए एक पंक्ति के साथ एक 'सामान्यीकृत तालिका' थी संयोजन तो उत्तर पाने के लिए क्वेरी उतनी ही सरल होगी जितनी कि joining टेबल एक साथ।

काश, यह denormalized है resources . होने से कॉलम के रूप में:'संसाधन आईडी की सूची' को ';' से अलग किया गया चरित्र।

यदि हम 'संसाधन' कॉलम को पंक्तियों में बदल सकते हैं तो बहुत सी कठिनाइयाँ दूर हो जाती हैं क्योंकि टेबल जुड़ना आसान हो जाता है।

माना गया आउटपुट जेनरेट करने के लिए क्वेरी:

SELECT user_resource.user, 
       resource.data

FROM user_resource 
     JOIN integerseries AS isequence 
       ON isequence.id <= COUNT_IN_SET(user_resource.resources, ';') /* normalize */

     JOIN resource 
       ON resource.id = VALUE_IN_SET(user_resource.resources, ';', isequence.id)      
ORDER BY
       user_resource.user,  resource.data

आउटपुट:

user        data    
----------  --------
sampleuser  abcde   
sampleuser  azerty  
sampleuser  qwerty  
stacky      qwerty  
testuser    abcde   
testuser    azerty  

कैसे:

'चाल' एक ऐसी तालिका है जिसमें 1 से लेकर कुछ सीमा तक की संख्याएँ हों। मैं इसे integerseries कहता हूं . इसका उपयोग 'क्षैतिज' चीजों को बदलने के लिए किया जा सकता है जैसे:';' delimited strings rows . में .

इसके काम करने का तरीका यह है कि जब आप integerseries . के साथ 'शामिल हों' , आप एक cross join कर रहे हैं , जो 'स्वाभाविक रूप से' 'इनर जॉइन' के साथ होता है।

प्रत्येक पंक्ति integerseries . से भिन्न 'अनुक्रम संख्या' के साथ दोहराई जाती है तालिका जिसे हम उस सूची में 'संसाधन' के 'सूचकांक' के रूप में उपयोग करते हैं जिसे हम उस row के लिए उपयोग करना चाहते हैं ।

यह विचार है:

  • सूची में मदों की संख्या गिनें।
  • सूची में अपनी स्थिति के आधार पर प्रत्येक आइटम को निकालें।
  • integerseries का उपयोग करें एक पंक्ति को user . से व्यक्तिगत 'संसाधन आईडी' निकालने वाली पंक्तियों के समूह में बदलने के लिए .resources जैसे-जैसे हम आगे बढ़ते हैं।

मैंने दो कार्यों का उपयोग करने का निर्णय लिया:

  • फ़ंक्शन जिसने 'सीमांकित स्ट्रिंग सूची' और 'इंडेक्स' दिया है, सूची में स्थिति पर मान वापस कर देगा। मैं इसे कॉल करता हूं:VALUE_IN_SET . यानी 'ए;बी;सी' और 2 का 'इंडेक्स' दिया गया तो यह 'बी' लौटाता है।

  • फ़ंक्शन जिसने 'सीमांकित स्ट्रिंग सूची' दी है, सूची में आइटम्स की संख्या की गिनती लौटाएगा। मैं इसे कॉल करता हूं:COUNT_IN_SET . यानी दिया गया 'ए;बी;सी' 3 लौटाएगा

यह पता चला है कि वे दो कार्य और integerseries delimited items list in a column

क्या यह काम करता है?

';' delimited string in column . यह 'cross_join' (isequence.id के कारण जेनरेट किए गए मानों सहित सभी कॉलम दिखाता है। resources_index . के रूप में ):

SELECT user_resource.user, 
       user_resource.resources,
       COUNT_IN_SET(user_resource.resources, ';')                AS resources_count, 
       isequence.id                                              AS resources_index,
       VALUE_IN_SET(user_resource.resources, ';', isequence.id)  AS resources_value
FROM 
     user_resource 
     JOIN  integerseries AS isequence 
       ON  isequence.id <= COUNT_IN_SET(user_resource.resources, ';')
ORDER BY
       user_resource.user, isequence.id

'सामान्यीकृत' तालिका आउटपुट:

user        resources  resources_count  resources_index  resources_value  
----------  ---------  ---------------  ---------------  -----------------
sampleuser  1;2;3                    3                1  1                
sampleuser  1;2;3                    3                2  2                
sampleuser  1;2;3                    3                3  3                
stacky      2                        1                1  2                
testuser    1;3                      2                1  1                
testuser    1;3                      2                2  3                

उपरोक्त 'सामान्यीकृत' का उपयोग करना user_resources तालिका, यह आवश्यक आउटपुट प्रदान करने के लिए एक सरल जुड़ाव है:

आवश्यक कार्य (ये सामान्य कार्य हैं जिनका उपयोग कहीं भी किया जा सकता है )

नोट:इन कार्यों के नाम mysql FIND_IN_SET फ़ंक्शन . यानी वे स्ट्रिंग सूचियों के संबंध में समान कार्य करते हैं?

COUNT_IN_SET फ़ंक्शन:character delimited items की गिनती लौटाता है कॉलम में।

DELIMITER $$

DROP FUNCTION IF EXISTS `COUNT_IN_SET`$$

CREATE FUNCTION `COUNT_IN_SET`(haystack VARCHAR(1024), 
                               delim CHAR(1)
                               ) RETURNS INTEGER
BEGIN
      RETURN CHAR_LENGTH(haystack) - CHAR_LENGTH( REPLACE(haystack, delim, '')) + 1;
END$$

DELIMITER ;

VALUE_IN_SET फ़ंक्शन:delimited list का व्यवहार करता है एक one based array . के रूप में और दिए गए 'इंडेक्स' पर मान लौटाता है।

DELIMITER $$

DROP FUNCTION IF EXISTS `VALUE_IN_SET`$$

CREATE FUNCTION `VALUE_IN_SET`(haystack VARCHAR(1024), 
                               delim CHAR(1), 
                               which INTEGER
                               ) RETURNS VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci
BEGIN
      RETURN  SUBSTRING_INDEX(SUBSTRING_INDEX(haystack, delim, which),
                     delim,
                     -1);
END$$

DELIMITER ;

संबंधित जानकारी:

टेबल (डेटा के साथ):

CREATE TABLE `integerseries` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=500 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

/*Data for the table `integerseries` */

insert  into `integerseries`(`id`) values (1);
insert  into `integerseries`(`id`) values (2);
insert  into `integerseries`(`id`) values (3);
insert  into `integerseries`(`id`) values (4);
insert  into `integerseries`(`id`) values (5);
insert  into `integerseries`(`id`) values (6);
insert  into `integerseries`(`id`) values (7);
insert  into `integerseries`(`id`) values (8);
insert  into `integerseries`(`id`) values (9);
insert  into `integerseries`(`id`) values (10);

संसाधन:

CREATE TABLE `resource` (
  `id` int(11) NOT NULL,
  `data` varchar(250) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

/*Data for the table `resource` */

insert  into `resource`(`id`,`data`) values (1,'abcde');
insert  into `resource`(`id`,`data`) values (2,'qwerty');
insert  into `resource`(`id`,`data`) values (3,'azerty');

User_resource:

CREATE TABLE `user_resource` (
  `user` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `resources` varchar(250) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

/*Data for the table `user_resource` */

insert  into `user_resource`(`user`,`resources`) values ('sampleuser','1;2;3');
insert  into `user_resource`(`user`,`resources`) values ('stacky','3');
insert  into `user_resource`(`user`,`resources`) values ('testuser','1;3');


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ProxySQL 2.0 में नया क्या है?

  2. MySQL REPLACE () - एक सबस्ट्रिंग के सभी इंस्टेंस को दूसरे स्ट्रिंग से बदलें

  3. MySQL संग्रहीत रूटीन में सरणी पास करें

  4. MySQL में डिफ़ॉल्ट बाधा कैसे जोड़ें

  5. MySQL के लिए एस्केप स्ट्रिंग पायथन