Son kayda alınıyor her grupta
Aşağıda gösterildiği gibi veri içeren bir tablo messages
:
Id Name Other_Columns
-------------------------
1 A A_data_1
2 A A_data_2
3 A A_data_3
4 B B_data_1
5 B B_data_2
6 C C_data_1
Eğer bir sorgu çalıştırırsanız select * from messages group by name
sonuç olarak alacağım:
1 A A_data_1
4 B B_data_1
6 C C_data_1
Ne sorgu aşağıdaki sonuç verecektir?
3 A A_data_3
5 B B_data_2
6 C C_data_1
Diğer bir deyişle, her grubun son kaydı iade edilmelidir.
Şu anda bu kullandığım sorgu
select * from (select * from messages ORDER BY id DESC) AS x GROUP BY name
Ama bu son derece verimsiz görünüyor. Aynı sonuca ulaşmak için başka yollar?
CEVAP
Çözüm bu şekilde yazıyorum:
SELECT m1.*
FROM messages m1 LEFT JOIN messages m2
ON (m1.name = m2.name AND m1.id < m2.id)
WHERE m2.id IS NULL;
Performansı, bir çözüm veya başka daha iyi, verilerin yapısına bağlı olabilir. Her iki sorgu test ve veritabanı verilen performans en iyi olanı kullanmalısınız.
Örneğin, StackOverflow Ağustos veri dökümü bir kopyası var. Kıyaslama için kullanacağım. Posts
tablo 1,114,357 satır vardır. Bu 2.40 GHz Pro benim Macbook üzerinde MySQL 5.0.75 üzerinde çalışıyor.
Sorgusu, belirli bir kullanıcı KİMLİĞİ (benim) en son post bulmak için yazacağım.
İlk teknik shown @tarafından Eric sorgu GROUP BY
ile kullanma:
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
bile analizi üzerinde 16 saniye sürer:
---- ------------- ------------ -------- ---------------------------- ------------- --------- -------------- --------- -------------
| 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)
Şimdi üretmek aynı sorgu sonucu LEFT JOIN
ile benim tekniği:
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
analiz her iki tablonun dizinlerini kullanmak mümkün olduğunu gösterir:
---- ------------- ------- ------ ---------------------------- ------------- --------- ------- ------ --------------------------------------
| 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)
İşte Posts
masam için DDL:
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;
Grup, her grupta ilk satır seçmek?...
En basit Twitter API ile alınıyor user...
Alt işlemi çıkış alınıyor.()çağrı...
Çekirdek Veri fon üzerinden alınıyor N...
Öğe için hata alınıyor üst: verilen ad...