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

प्रत्येक समूह में अंतिम रिकॉर्ड प्राप्त करना - MySQL

MySQL 8.0 अब लगभग सभी लोकप्रिय SQL कार्यान्वयनों की तरह विंडोिंग फ़ंक्शन का समर्थन करता है। इस मानक सिंटैक्स के साथ, हम सबसे बड़ी-एन-प्रति-समूह क्वेरी लिख सकते हैं:

WITH ranked_messages AS (
  SELECT m.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id DESC) AS rn
  FROM messages AS m
)
SELECT * FROM ranked_messages WHERE rn = 1;

नीचे मूल उत्तर है जो मैंने इस प्रश्न के लिए 2009 में लिखा था:

मैं समाधान इस तरह लिखता हूं:

SELECT m1.*
FROM messages m1 LEFT JOIN messages m2
 ON (m1.name = m2.name AND m1.id < m2.id)
WHERE m2.id IS NULL;

प्रदर्शन के संबंध में, आपके डेटा की प्रकृति के आधार पर, एक समाधान या दूसरा बेहतर हो सकता है। इसलिए आपको दोनों प्रश्नों का परीक्षण करना चाहिए और अपने डेटाबेस को देखते हुए बेहतर प्रदर्शन वाले प्रश्नों का उपयोग करना चाहिए।

उदाहरण के लिए, मेरे पास StackOverflow अगस्त डेटा डंप की एक कॉपी है . मैं बेंचमार्किंग के लिए इसका इस्तेमाल करूंगा। Posts . में 1,114,357 पंक्तियां हैं टेबल। यह MySQL पर चल रहा है मेरे मैकबुक प्रो 2.40GHz पर 5.0.75।

मैं किसी दिए गए उपयोगकर्ता आईडी (मेरा) के लिए नवीनतम पोस्ट खोजने के लिए एक प्रश्न लिखूंगा।

सबसे पहले तकनीक का उपयोग करना दिखाया गया @Eric द्वारा GROUP BY . के साथ एक सबक्वेरी में:

SELECT p1.postid
FROM Posts p1
INNER JOIN (SELECT pi.owneruserid, MAX(pi.postid) AS maxpostid
            FROM Posts pi GROUP BY pi.owneruserid) p2
  ON (p1.postid = p2.maxpostid)
WHERE p1.owneruserid = 20860;

1 row in set (1 min 17.89 sec)

यहां तक ​​कि EXPLAIN विश्लेषण 16 सेकंड से अधिक समय लेता है:

+----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+
| id | select_type | table      | type   | possible_keys              | key         | key_len | ref          | rows    | Extra       |
+----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+
|  1 | PRIMARY     | <derived2> | ALL    | NULL                       | NULL        | NULL    | NULL         |   76756 |             | 
|  1 | PRIMARY     | p1         | eq_ref | PRIMARY,PostId,OwnerUserId | PRIMARY     | 8       | p2.maxpostid |       1 | Using where | 
|  2 | DERIVED     | pi         | index  | NULL                       | OwnerUserId | 8       | NULL         | 1151268 | Using index | 
+----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+
3 rows in set (16.09 sec)

अब मेरी तकनीक LEFT JOIN के साथ :

SELECT p1.postid
FROM Posts p1 LEFT JOIN posts p2
  ON (p1.owneruserid = p2.owneruserid AND p1.postid < p2.postid)
WHERE p2.postid IS NULL AND p1.owneruserid = 20860;

1 row in set (0.28 sec)

EXPLAIN विश्लेषण से पता चलता है कि दोनों टेबल अपने इंडेक्स का उपयोग करने में सक्षम हैं:

+----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+
| id | select_type | table | type | possible_keys              | key         | key_len | ref   | rows | Extra                                |
+----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+
|  1 | SIMPLE      | p1    | ref  | OwnerUserId                | OwnerUserId | 8       | const | 1384 | Using index                          | 
|  1 | SIMPLE      | p2    | ref  | PRIMARY,PostId,OwnerUserId | OwnerUserId | 8       | const | 1384 | Using where; Using index; Not exists | 
+----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+
2 rows in set (0.00 sec)

मेरे Posts के लिए डीडीएल ये रहा तालिका:

CREATE TABLE `posts` (
  `PostId` bigint(20) unsigned NOT NULL auto_increment,
  `PostTypeId` bigint(20) unsigned NOT NULL,
  `AcceptedAnswerId` bigint(20) unsigned default NULL,
  `ParentId` bigint(20) unsigned default NULL,
  `CreationDate` datetime NOT NULL,
  `Score` int(11) NOT NULL default '0',
  `ViewCount` int(11) NOT NULL default '0',
  `Body` text NOT NULL,
  `OwnerUserId` bigint(20) unsigned NOT NULL,
  `OwnerDisplayName` varchar(40) default NULL,
  `LastEditorUserId` bigint(20) unsigned default NULL,
  `LastEditDate` datetime default NULL,
  `LastActivityDate` datetime default NULL,
  `Title` varchar(250) NOT NULL default '',
  `Tags` varchar(150) NOT NULL default '',
  `AnswerCount` int(11) NOT NULL default '0',
  `CommentCount` int(11) NOT NULL default '0',
  `FavoriteCount` int(11) NOT NULL default '0',
  `ClosedDate` datetime default NULL,
  PRIMARY KEY  (`PostId`),
  UNIQUE KEY `PostId` (`PostId`),
  KEY `PostTypeId` (`PostTypeId`),
  KEY `AcceptedAnswerId` (`AcceptedAnswerId`),
  KEY `OwnerUserId` (`OwnerUserId`),
  KEY `LastEditorUserId` (`LastEditorUserId`),
  KEY `ParentId` (`ParentId`),
  CONSTRAINT `posts_ibfk_1` FOREIGN KEY (`PostTypeId`) REFERENCES `posttypes` (`PostTypeId`)
) ENGINE=InnoDB;

टिप्पणीकारों के लिए नोट:यदि आप MySQL के भिन्न संस्करण, भिन्न डेटासेट, या भिन्न तालिका डिज़ाइन के साथ एक और बेंचमार्क चाहते हैं, तो इसे स्वयं करने के लिए स्वतंत्र महसूस करें। मैंने ऊपर तकनीक दिखाई है। स्टैक ओवरफ्लो यहां आपको यह दिखाने के लिए है कि सॉफ्टवेयर विकास कार्य कैसे करें, न कि आपके लिए सभी कार्य करने के लिए।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. एमएस एसक्यूएल सर्वर 2008 के साथ एंड्रॉइड कनेक्ट करना

  2. MySQL अद्यतन मामला कब/फिर/अन्यथा

  3. पीडीओ का उपयोग करके सहायक फ़ंक्शन डालें/अपडेट करें

  4. MySQL में एक स्ट्रिंग को कई बार दोहराएं - REPEAT ()

  5. MySQL विशेषक असंवेदनशील खोज (स्पेनिश उच्चारण)