සෑම කණ්ඩායමකම අවසන් වාර්තාව ලබා ගැනීම - MySQL


989

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

මම විමසුමක් ක්‍රියාත්මක කරන්නේ නම්, එහි ප්‍රති select * from messages group by nameresult ලය මට ලැබෙනුයේ:

1    A       A_data_1
4    B       B_data_1
6    C       C_data_1

පහත ප්‍රති result ලය ලබා දෙන විමසුම කුමක්ද?

3    A       A_data_3
5    B       B_data_2
6    C       C_data_1

එනම්, එක් එක් කණ්ඩායමෙහි අවසාන වාර්තාව ආපසු ලබා දිය යුතුය.

දැනට, මම භාවිතා කරන විමසුම මෙයයි:

SELECT
  *
FROM (SELECT
  *
FROM messages
ORDER BY id DESC) AS x
GROUP BY name

නමුත් මෙය බෙහෙවින් අකාර්යක්ෂම බව පෙනේ. එකම ප්‍රති result ලය ලබා ගැනීමට වෙනත් ක්‍රම තිබේද?


2
වඩාත් කාර්යක්ෂම විසඳුමක් සඳහා stackoverflow.com/questions/1379565/… හි පිළිගත් පිළිතුර බලන්න
eyaler

ක අනුපිටපත් stackoverflow.com/q/121387/684229
TMS

7
ඔබට DESC එකතු කළ නොහැක්කේ ඇයි, එනම් DESC නමින් පණිවිඩ සමූහයෙන් * තෝරන්න
කිම් ප්‍රින්ස්


2
ImKimPrince ඔබ යෝජනා කරන පිළිතුර අපේක්ෂා කළ දේ නොකරන බව පෙනේ! මම ඔබේ ක්‍රමය අත්හදා බැලූ අතර එය එක් එක් කණ්ඩායම සඳහා පළමු පේළිය ගෙන DESC ඇණවුම් කළෙමි. එය සෑම කණ්ඩායමකම අවසාන පේළිය
නොගනී

Answers:


1007

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;

කාර්ය සාධනය සම්බන්ධයෙන්, ඔබේ දත්තවල ස්වභාවය අනුව එක් විසඳුමක් හෝ වෙනත් විසඳුමක් වඩා හොඳ විය හැකිය. එබැවින් ඔබ විමසුම් දෙකම පරීක්ෂා කර ඔබගේ දත්ත ගබඩාවට ලබා දී ඇති කාර්ය සාධනයට වඩා හොඳ එකක් භාවිතා කළ යුතුය.

උදාහරණයක් ලෙස, මට ස්ටැක් ඕවර්ෆ්ලෝ අගෝස්තු දත්ත ඩම්ප් පිටපතක් තිබේ . මම එය මිණුම් සලකුණු කිරීම සඳහා භාවිතා කරමි. වගුවේ පේළි 1,114,357 ක් ඇත Posts. මෙය MySQL මත ක්‍රියාත්මක වේ මගේ මැක්බුක් ප්‍රෝ 2.40GHz 5.0.75 මත .

දී ඇති පරිශීලක හැඳුනුම්පතක් (මගේ) සඳහා නවතම ලිපිය සොයා ගැනීමට මම විමසුමක් ලියමි.

මුලින් උපසිරැසියකින් @ එරික් විසින් පෙන්වන තාක්ෂණය භාවිතා කිරීම 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)

දැන් මගේ තාක්‍ෂණය භාවිතා කරමින් එකම විමසුම් ප්‍රති result ලබා දෙන්න 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;

8
ඇත්තටම? ඔබට ඇතුළත් කිරීම් ටොන් ගණනක් තිබේ නම් කුමක් සිදුවේද? නිදසුනක් ලෙස, ඔබ අභ්‍යන්තර අනුවාද පාලනයක් සමඟ වැඩ කරන්නේ නම්, කියන්න, සහ ඔබට ගොනුවකට අනුවාද ටොන් ගණනක් තිබේ නම්, එම සම්බන්ධ වීමේ ප්‍රති result ලය අති විශාල වනු ඇත. ඔබ කවදා හෝ මෙම ක්‍රමය සමඟ අනුකාරක ක්‍රමය මිණුම් සලකුණු කර තිබේද? ජයග්‍රහණය කරන්නේ කුමක් දැයි දැන ගැනීමට මට කුතුහලයක් ඇත, නමුත් මුලින් ඔබෙන් විමසීමට තරම් කුතුහලයක් නැත.
එරික්

2
යම් පරීක්ෂණයක් කළා. කුඩා මේසයක් මත (k 300k වාර්තා, k 190k කණ්ඩායම්, එබැවින් දැවැන්ත කණ්ඩායම් හෝ කිසිවක් නොවේ), විමසුම් ගැටගැසී ඇත (තත්පර 8 බැගින්).
එරික්

1
@BillKarwin: බලන්න meta.stackexchange.com/questions/123017 , ආදම් Rackis 'පිළිතුර පහත විශේෂයෙන් අදහස්. නව ප්‍රශ්නයට ඔබේ පිළිතුර නැවත ලබා ගැනීමට අවශ්‍ය නම් මට දන්වන්න.
රොබට් හාවි

3
Im අද්විතීය, <=ඔබට අද්විතීය නොවන තීරුවක් තිබේ නම් එය උදව් නොකරයි. ටයිබ්‍රේකර් ලෙස ඔබ අද්විතීය තීරුවක් භාවිතා කළ යුතුය.
බිල් කාර්වින්

2
පේළි ගණන වැඩි වන විට හෝ කණ්ඩායම් විශාල වන විට කාර්ය සාධනය on ාතීය ලෙස පිරිහෙයි. උදාහරණයක් ලෙස දින 5 කින් සමන්විත කණ්ඩායමක් වම් පසින් පේළි 4 + 3 + 2 + 1 + 1 = 11 ක් ලබා දෙන අතර ඉන් එක් පේළියක් අවසානයේ පෙරීම සිදු කරයි. කණ්ඩායම් ප්‍රති results ල සමඟ සම්බන්ධ වීමේ කාර්ය සාධනය පාහේ රේඛීය වේ. ඔබගේ පරීක්ෂණ දෝෂ සහිත බව පෙනේ.
සල්මාන් ඒ

152

UPD: 2017-03-31, MySQL හි 5.7.5 අනුවාදය ONLY_FULL_GROUP_BY ස්විචය පෙරනිමියෙන් සක්‍රීය කර ඇත (එබැවින් විමසුම් මගින් නිර්ණය නොකරන ලද GROUP BY විමසීම් අක්‍රීය විය). එපමණක් නොව, ඔවුන් GROUP BY ක්‍රියාත්මක කිරීම යාවත්කාලීන කළ අතර ආබාධිත ස්විචය සමඟ වුවද විසඳුම බලාපොරොත්තු වූ පරිදි ක්‍රියාත්මක නොවනු ඇත. යමෙකු පරීක්ෂා කළ යුතුය.

කණ්ඩායම් තුළ ඇති අයිතම ගණන තරමක් කුඩා වන විට ඉහත බිල් කාර්වින්ගේ විසඳුම හොඳින් ක්‍රියාත්මක වේ, නමුත් කණ්ඩායම් තරමක් විශාල වූ විට විමසුමේ ක්‍රියාකාරිත්වය නරක වනු ඇත, මන්ද විසඳුමට අවශ්‍ය n*n/2 + n/2වන්නේ IS NULLසැසඳීම් පමණි .

මම කණ්ඩායම් 18684446සමඟ InnoDB පේළි වගුවක මගේ පරීක්ෂණ සිදු කළෙමි 1182. වගුවේ ක්‍රියාකාරී පරීක්ෂණ සඳහා පරීක්ෂණ ප්‍රති ult ල අඩංගු වන (test_id, request_id)අතර ප්‍රාථමික යතුර ලෙස එය ඇත. මේ අනුව, test_idකණ්ඩායමක් වන අතර මම request_idඑක් එක් සඳහා අන්තිමයන් සොයමින් සිටියෙමි test_id.

බිල්ගේ විසඳුම දැනටමත් මගේ ඩෙල් e4310 මත පැය කිහිපයක් තිස්සේ ක්‍රියාත්මක වන අතර එය ආවරණ දර්ශකයක් මත ක්‍රියාත්මක වුවද එය අවසන් වන්නේ කවදාදැයි මම නොදනිමි (එබැවින් using indexEXPLAIN හි).

එකම අදහස් මත පදනම් වූ වෙනත් විසඳුම් කිහිපයක් මා සතුව ඇත:

  • යටින් පවතින දර්ශකය BTREE දර්ශකය නම් (සාමාන්‍යයෙන් එය එසේ වේ), විශාලතම (group_id, item_value)යුගලය සෑම එකක් තුළම ඇති අවසාන අගය වේ group_id, එය එක් එක් සඳහා පළමු වේgroup_id අප දර්ශකය හරහා බැසීමේ අනුපිළිවෙලින් ගමන් කරන්නේ නම් එය ;
  • අපි දර්ශකයකින් ආවරණය වන අගයන් කියවන්නේ නම්, අගයන් දර්ශකයේ අනුපිළිවෙලින් කියවනු ලැබේ;
  • සෑම දර්ශකයකම ව්‍යංගයෙන් ප්‍රාථමික යතුරු තීරු අඩංගු වේ (එනම් ප්‍රාථමික යතුර ආවරණ දර්ශකයේ ඇත). පහත දැක්වෙන විසඳුම් වලදී මම සෘජුවම ප්‍රාථමික යතුර මත ක්‍රියාත්මක වන අතර, ඔබට අවශ්‍ය නම්, ඔබට ප්‍රති key ලය තුළ ප්‍රාථමික යතුරු තීරු එක් කිරීමට අවශ්‍ය වනු ඇත.
  • බොහෝ අවස්ථාවන්හීදී අවශ්‍ය අනුපිළිවෙලින් අවශ්‍ය පේළි අයිඩී උපවගන්තියක එකතු කර හැඳුනුම්පතේ අනුකමිටුවේ ප්‍රති result ලයට සම්බන්ධ වීම වඩා ලාභදායී වේ. අනුකාරක ප්‍රති result ලයේ එක් එක් පේළිය සඳහා ප්‍රාථමික යතුර මත පදනම්ව MySQL හට තනි ලබා ගැනීමක් අවශ්‍ය වන බැවින්, අනුකාරකයට පළමු වරට සම්බන්ධ වන අතර පේළි අනුකාරකයේ අයිඩී අනුපිළිවෙලට ප්‍රතිදානය වනු ඇත (අප විසින් පැහැදිලි නියෝගය මඟ හැරියහොත් බැඳීම සඳහා)

MySQL දර්ශක භාවිතා කරන ක්‍රම 3 ක් සමහර විස්තර තේරුම් ගැනීමට හොඳ ලිපියකි.

විසඳුම 1

මෙය ඇදහිය නොහැකි තරම් වේගවත්, මගේ 18M + පේළි සඳහා තත්පර 0,8 ක් ගතවේ:

SELECT test_id, MAX(request_id) AS request_id
FROM testresults
GROUP BY test_id DESC;

ඔබට ඇණවුම ASC ලෙස වෙනස් කිරීමට අවශ්‍ය නම්, එය අනුකාරකයකට දමා, අයිඩී පමණක් ආපසු ලබා දී ඉතිරි තීරුවලට සම්බන්ධ වීමට එය අනුකාරකය ලෙස භාවිතා කරන්න:

SELECT test_id, request_id
FROM (
    SELECT test_id, MAX(request_id) AS request_id
    FROM testresults
    GROUP BY test_id DESC) as ids
ORDER BY test_id;

මෙය මගේ දත්ත සඳහා තත්පර 1,2 ක් ගතවේ.

විසඳුම 2

මගේ වගුව සඳහා තත්පර 19 ක් පමණ ගතවන තවත් විසඳුමක් මෙන්න:

SELECT test_id, request_id
FROM testresults, (SELECT @group:=NULL) as init
WHERE IF(IFNULL(@group, -1)=@group:=test_id, 0, 1)
ORDER BY test_id DESC, request_id DESC

එමඟින් පරීක්ෂණ අවරෝහණ පිළිවෙලට ලබා දෙයි. එය සම්පූර්ණ දර්ශක පරිලෝකනයක් කරන බැවින් එය වඩා මන්දගාමී වන නමුත් සෑම කණ්ඩායමක් සඳහාම N උපරිම පේළි ප්‍රතිදානය කරන්නේ කෙසේද යන්න පිළිබඳ අදහසක් ඔබට ලබා දීමට මෙහි ඇත.

විමසුමේ අවාසිය නම් එහි ප්‍රති result ලය විමසුම් හැඹිලියෙන් හැඹිලිගත කළ නොහැකි වීමයි.


කරුණාකර ඔබගේ වගු කුණු කූඩයකට සම්බන්ධ කරන්න එවිට මිනිසුන්ට එය ඔවුන්ගේ වේදිකාවල පරීක්ෂා කළ හැකිය.
පැසීරියර්

3
විසඳුම 1 වැඩ කළ නොහැක, වගන්තිය අනුව සමූහයක් නොමැතිව ඔබට request_id තෝරාගත නොහැක,
giò

2
@ giò, මෙය පිළිතුර අවුරුදු 5 යි. MySQL 5.7.5 තෙක් ONLY_FULL_GROUP_BY පෙරනිමියෙන් අක්‍රිය කර ඇති අතර මෙම විසඳුම dev.mysql.com/doc/relnotes/mysql/5.7/en/… කොටුවෙන් පිටත ක්‍රියාත්මක විය . ඔබ මාදිලිය අක්‍රිය කළ විට විසඳුම තවමත් ක්‍රියාත්මක වේදැයි මට විශ්වාස නැත, මන්ද GROUP BY ක්‍රියාත්මක කිරීම වෙනස් කර ඇති බැවිනි.
අළුත්

පළමු විසඳුමේදී ඔබට ASC අවශ්‍ය නම්, ඔබ MAX MIN වෙත හරවන්නේ නම් එය ක්‍රියාත්මක වේද?
ජින්

In ජින්ඉස්රායෙල්, සෑම කණ්ඩායමකම ඉහළින් ඔබට පෙරනිමියෙන් MIN ඇත (එය ආවරණ දර්ශකයේ අනුපිළිවෙලයි): SELECT test_id, request_id FROM testresults GROUP BY test_id;සෑම ටෙස්ට්_අයිඩයක් සඳහාම අවම ඉල්ලීම්_අයිඩයක් ලබා දෙනු ඇත.
අළුත්

103

ඔබ එහි අඩක් පමණ සිටින නිසා නිවැරදි සමූහකරණය නැවත ලබා දීමට ඔබේ අනුකාරකය භාවිතා කරන්න .

මේක උත්සාහ කරන්න:

select
    a.*
from
    messages a
    inner join 
        (select name, max(id) as maxid from messages group by name) as b on
        a.id = b.maxid

එය idඔබට අවශ්‍ය නොවේ නම් :

select
    a.*
from
    messages a
    inner join 
        (select name, max(other_col) as other_col 
         from messages group by name) as b on
        a.name = b.name
        and a.other_col = b.other_col

මේ ආකාරයෙන්, ඔබ ඉතා මන්දගාමී / අකාර්යක්ෂමතාවයට නැඹුරු වන සහසම්බන්ධිත අනුකමිටු සහ / හෝ ඔබේ අනුකොටස්වල ඇණවුම් කිරීමෙන් වළකින්න.


1
සමඟ විසඳුම සඳහා අවවාදයක් සටහන් කරන්න other_col: එම තීරුව අද්විතීය නොවේ nameනම්, ඒවා ගැටගැසෙන්නේ නම්, ඔබට එකවරම වාර්තා කිහිපයක්ම ලබා ගත හැකිය max(other_col). මගේ අවශ්‍යතාවයන් සඳහා විසඳුමක් විස්තර කරන මෙම ලිපිය මට හමු විය , එහිදී මට හරියටම එක් වාර්තාවක් අවශ්‍ය වේ name.
එරික් සිමොන්ටන්

සමහර අවස්ථාවන්හිදී ඔබට මෙම විසඳුම භාවිතා කළ හැකි නමුත් පිළිගත් විසඳුම මත පමණි.
tom10271

මගේ අත්දැකීම් අනුව, එය මන්දගාමී / අකාර්යක්ෂමතාවයට නැඹුරු වන සමස්ත නරක පණිවිඩ වගුව කාණ්ඩගත කරයි ! වෙනත් වචන වලින් කිවහොත්, subquery සම්පූර්ණ වගුවක් ස්කෑන් අවශ්ය බව සටහන් හා ඇරඹුම් බව මත පාදකව නැහැ ... ඔබේ කාරණයක් මගේ නොවන යමක් කරන්නේ නම් මිස. එබැවින් මෙම විසඳුම මුළු වගුවම මතකයේ තබා ගැනීම මත බෙහෙවින් රඳා පවතී.
ටිමෝ

එම ප්රතිලාභ ඇත INDEX(name, id)හාINDEX(name, other_col)
රික් ජේම්ස්

59

මම වෙනස් විසඳුමකට පැමිණියෙමි, එනම් එක් එක් කණ්ඩායම තුළ අවසාන පෝස්ට් සඳහා හැඳුනුම්පත් ලබා ගැනීම, ඉන්පසු පළමු වගුවේ ප්‍රති result ලය භාවිතා කරමින් පණිවිඩ වගුවෙන් තෝරන්න WHERE x IN.

SELECT id, name, other_columns
FROM messages
WHERE id IN (
    SELECT MAX(id)
    FROM messages
    GROUP BY name
);

වෙනත් විසඳුම් සමඟ සසඳන විට මෙය ක්‍රියාත්මක වන්නේ කෙසේදැයි මම නොදනිමි, නමුත් එය පේළි මිලියන 3+ ක් සහිත මගේ වගුව සඳහා දර්ශනීය ලෙස ක්‍රියා කළේය. (1200+ ප්‍රති results ල සමඟ තත්පර 4 ක් ක්‍රියාත්මක කිරීම)

මෙය MySQL සහ SQL සේවාදායකයේ ක්‍රියාත්මක විය යුතුය.


ඔබට (නම, හැඳුනුම්පත) දර්ශකයක් ඇති බවට වග බලා ගන්න.
සැමුවෙල් ඔස්ලන්ඩ්

1
ස්වයං සම්බන්ධ වීම වඩා හොඳය
anwerj

මම ඔබෙන් යමක් ඉගෙන ගත්තා එය හොඳ රැකියාවක් වන අතර මෙම විමසුම වේගවත් වේ
හම්ෆ්රි

36

උප විමසුම් ෆෙඩල් ලින්ක් මගින් විසඳුම

select * from messages where id in
(select max(id) from messages group by Name)

විසඳුම සම්බන්ධ වීමෙන් කොන්දේසි ෆෙඩල් සබැඳිය

select m1.* from messages m1 
left outer join messages m2 
on ( m1.id<m2.id and m1.name=m2.name )
where m2.id is null

මෙම තනතුර සඳහා හේතුව වන්නේ ෆෙඩල් සබැඳිය පමණක් ලබා දීමයි. එකම SQL දැනටමත් වෙනත් පිළිතුරු වලින් සපයා ඇත.


1
Lex ඇලෙක්සැන්ඩර්සුරෆෙල් mysql5.5 දැන් ෆෙඩෙල් හි නොමැත, එය භාවිතා කරමින් ෆෙඩල් ලින්ක් නිර්මාණය කරන ලදි. දැන් දිනක් ෆෙඩල් විසින් mysql5.6 සඳහා සහය දක්වයි, මම දත්ත සමුදාය mysql 5.6 ලෙස වෙනස් කර ඇති අතර මට ක්‍රමෝපාය ගොඩනඟා SQL ධාවනය කළ හැකිය.
විපින්

වේගය, ක්‍රියාකාරිත්වය හෝ වෙනත් සාධක පිළිබඳ ප්‍රවේශයන් දෙක අතර වෙනසක් තිබේද?
ඩී හඩ්සන්

8

සැලකිය යුතු වේගයකින් යුත් ප්‍රවේශයක් පහත පරිදි වේ.

SELECT * 
FROM messages a
WHERE Id = (SELECT MAX(Id) FROM messages WHERE a.Name = Name)

ප්‍රති ult ලය

Id  Name    Other_Columns
3   A   A_data_3
5   B   B_data_2
6   C   C_data_1

මෙය idඔබට අවශ්‍ය ආකාරයට ඇණවුම් කර ඇතැයි උපකල්පනය කරයි . පොදුවේ ගත් කල වෙනත් තීරුවක් අවශ්‍ය වේ.
රික් ජේම්ස්

6

මෙන්න යෝජනා දෙකක්. පළමුව, mysql ROW_NUMBER () සඳහා සහය දක්වන්නේ නම්, එය ඉතා සරල ය:

WITH Ranked AS (
  SELECT Id, Name, OtherColumns,
    ROW_NUMBER() OVER (
      PARTITION BY Name
      ORDER BY Id DESC
    ) AS rk
  FROM messages
)
  SELECT Id, Name, OtherColumns
  FROM messages
  WHERE rk = 1;

මම උපකල්පනය කරන්නේ "අන්තිම" යන්නෙන් ඔබ අදහස් කරන්නේ අවසන් වරට අයිඩී අනුපිළිවෙලට බවයි. එසේ නොවේ නම්, ඒ අනුව ROW_NUMBER () කවුළුවේ ORDER BY වගන්තිය වෙනස් කරන්න. ROW_NUMBER () ලබා ගත නොහැකි නම්, මෙය තවත් විසඳුමකි:

දෙවනුව, එසේ නොවේ නම්, මෙය බොහෝ විට ඉදිරියට යාමට හොඳ ක්‍රමයකි:

SELECT
  Id, Name, OtherColumns
FROM messages
WHERE NOT EXISTS (
  SELECT * FROM messages as M2
  WHERE M2.Name = messages.Name
  AND M2.Id > messages.Id
)

වෙනත් වචන වලින් කිවහොත්, එකම නම සහිත පසු-හැඳුනුම් පණිවිඩයක් නොමැති පණිවිඩ තෝරන්න.


8
MySQL ROW_NUMBER () හෝ CTE සඳහා සහය නොදක්වයි.
බිල් කාර්වින්

1
MySQL 8.0 (සහ MariaDB 10.2) දැන් සහය ROW_NUMBER()සහ CTEs.
රික් ජේම්ස්

6

මම තවමත් විශාල ඩීබී සමඟ පරීක්‍ෂා කර නැති නමුත් මෙය වගු හා සම්බන්ධ වීමට වඩා වේගවත් විය හැකි යැයි මම සිතමි:

SELECT *, Max(Id) FROM messages GROUP BY Name

14
මෙය අත්තනෝමතික දත්ත ලබා දෙයි. වෙනත් වචන වලින් කිවහොත්, ආපසු එන තීරු MAX (Id) සමඟ වාර්තාවෙන් නොතිබිය හැකිය.
හානි

WHERE කොන්දේසියක් සහිත වාර්තා කට්ටලයකින් උපරිම හැඳුනුම්පත තෝරා ගැනීමට ප්‍රයෝජනවත් වේ: "නිෂ්පාදිතයෙන් උපරිම (හැඳුනුම්පත) තෝරන්න කොතැනද Pn = '" + Pn + "" "එය එකම Pn සහිත වාර්තා සමූහයකින් උපරිම හැඳුනුම්පත ලබා දෙයි. C # ප්‍රති result ලය ලබා ගැනීම සඳහා reader.GetString (0) භාවිතා කරන්න
නිකොලා

5

GROUP_CONCATඇණවුම අනුව භාවිතා කරමින් අවසන් වරට අදාළ වාර්තාව ලබා ගැනීමට සහ SUBSTRING_INDEXලැයිස්තුවෙන් එක් වාර්තාවක් තෝරා ගැනීමට මෙන්න තවත් ක්‍රමයක්

SELECT 
  `Id`,
  `Name`,
  SUBSTRING_INDEX(
    GROUP_CONCAT(
      `Other_Columns` 
      ORDER BY `Id` DESC 
      SEPARATOR '||'
    ),
    '||',
    1
  ) Other_Columns 
FROM
  messages 
GROUP BY `Name` 

ඉහත විමසුම Other_Columnsඑකම Nameකණ්ඩායමේ ORDER BY id DESCසිටින සියල්ලන්ම Other_Columnsකාණ්ඩගත කරනු ඇති අතර භාවිතා ||කිරීම මා භාවිතා කර ඇති නඩුවේ සපයා ඇති බෙදුම්කරු සමඟ නිශ්චිත අනුපිළිවෙලකට බැසීමේ අනුපිළිවෙලට SUBSTRING_INDEXඑක්වනු ඇත, මෙම ලැයිස්තුවට ඉහළින් භාවිතා කිරීමෙන් පළමු එක තෝරා ගනු ඇත

Fiddle Demo


group_concat_max_lenඔබට හැසිරවිය හැකි පේළි ගණන සීමා කරන බව මතක තබා ගන්න.
රික් ජේම්ස්

5

එකම ප්‍රති results ල ලබා ගැනීම සඳහා විවිධ ක්‍රම රාශියක් ඇති බව පැහැදිලිය, ඔබේ ප්‍රශ්නය MySQL හි සෑම කණ්ඩායමකම අවසාන ප්‍රති results ල ලබා ගැනීමේ කාර්යක්ෂම ක්‍රමය කුමක්දැයි පෙනේ. ඔබ විශාල දත්ත ප්‍රමාණයක් සමඟ වැඩ කරන්නේ නම් සහ ඔබ MySQL හි නවතම අනුවාදයන් (5.7.21 සහ 8.0.4-rc වැනි) සමඟ InnoDB භාවිතා කරයි යැයි උපකල්පනය කරන්නේ නම් මෙය කිරීමට කාර්යක්ෂම ක්‍රමයක් නොතිබෙනු ඇත.

අපට සමහර විට පේළි මිලියන 60 කට වඩා ඇති වගු සමඟ මෙය කළ යුතුය.

මෙම උදාහරණ සඳහා මම දත්ත භාවිතා කරන්නේ පේළි මිලියන 1.5 ක් පමණ වන අතර එහිදී විමසුම් වලට දත්තවල සියලුම කණ්ඩායම් සඳහා ප්‍රති results ල සොයා ගත යුතුය. අපගේ සත්‍ය අවස්ථාවන්හිදී අපට බොහෝ විට කණ්ඩායම් 2,000 කින් පමණ දත්ත ආපසු ලබා දීමට අවශ්‍ය වනු ඇත (උපකල්පිත වශයෙන් දත්ත බොහෝමයක් පරීක්ෂා කිරීම අවශ්‍ය නොවේ).

මම පහත වගු භාවිතා කරමි:

CREATE TABLE temperature(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
  groupID INT UNSIGNED NOT NULL, 
  recordedTimestamp TIMESTAMP NOT NULL, 
  recordedValue INT NOT NULL,
  INDEX groupIndex(groupID, recordedTimestamp), 
  PRIMARY KEY (id)
);

CREATE TEMPORARY TABLE selected_group(id INT UNSIGNED NOT NULL, PRIMARY KEY(id)); 

උෂ්ණත්ව වගුව අහඹු වාර්තා මිලියන 1.5 ක් පමණ වන අතර විවිධ කණ්ඩායම් 100 ක් ඇත. තෝරාගත්_ සමූහය එම කණ්ඩායම් 100 සමඟ ජනාකීර්ණ වේ (අපගේ අවස්ථා වලදී මෙය සාමාන්‍යයෙන් සියලුම කණ්ඩායම් සඳහා 20% ට වඩා අඩු වනු ඇත).

මෙම දත්ත අහඹු බැවින් එහි අර්ථය වන්නේ පේළි කිහිපයකට එකම පටිගත කළ ටයිම්ස්ටැම්ප් තිබිය හැකි බවයි. අපට අවශ්‍ය වන්නේ එක් එක් කණ්ඩායම සඳහා අවසන් වරට පටිගත කරන ලද ටයිම්ස්ටැම්ප් සමඟ groupID අනුපිළිවෙලින් තෝරාගත් සියලුම කණ්ඩායම් ලැයිස්තුවක් ලබා ගැනීම සහ එකම කණ්ඩායමට එක හා සමාන ගැලපෙන පේළි එකකට වඩා තිබේ නම් එම පේළි වල අවසාන ගැලපෙන හැඳුනුම්පත.

උපකල්පිත වශයෙන් MySQL හි අවසාන () ශ්‍රිතයක් තිබේ නම් එය අවසාන පේළියේ අගයන් විශේෂ නියෝගයකින් වගන්තියකින් ලබා දුන්නේ නම් අපට කළ හැක්කේ:

SELECT 
  last(t1.id) AS id, 
  t1.groupID, 
  last(t1.recordedTimestamp) AS recordedTimestamp, 
  last(t1.recordedValue) AS recordedValue
FROM selected_group g
INNER JOIN temperature t1 ON t1.groupID = g.id
ORDER BY t1.recordedTimestamp, t1.id
GROUP BY t1.groupID;

සාමාන්‍ය GROUP BY ශ්‍රිත කිසිවක් භාවිතා නොකරන බැවින් මෙම නඩුවේ පේළි 100 ක් පමණක් පරීක්ෂා කිරීමට අවශ්‍ය වේ. මෙය තත්පර 0 කින් ක්‍රියාත්මක වන අතර එබැවින් ඉහළ කාර්යක්ෂමතාවයක් ඇත. සාමාන්‍යයෙන් MySQL හි අපි GROUP BY වගන්තිය අනුගමනය කරමින් ORDER BY වගන්තියක් දකිනු ඇත. කෙසේ වෙතත් අවසාන () ශ්‍රිතය සඳහා ORDER තීරණය කිරීම සඳහා මෙම ORDER BY වගන්තිය භාවිතා කරනු ලැබේ, එය GROUP BY ට පසුව නම් එය GROUPS ඇණවුම් කරනු ඇත. GROUP BY වගන්තියක් නොමැති නම්, ආපසු ලබා දුන් සියලු පේළි වල අවසාන අගයන් සමාන වේ.

කෙසේ වෙතත් MySQL සතුව මෙය නොමැත, එබැවින් එහි ඇති දේ පිළිබඳ විවිධ අදහස් දෙස බලමින් මේ කිසිවක් කාර්යක්ෂම නොවන බව ඔප්පු කරමු.

උදාහරණ 1

SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue
FROM selected_group g
INNER JOIN temperature t1 ON t1.id = (
  SELECT t2.id
  FROM temperature t2 
  WHERE t2.groupID = g.id
  ORDER BY t2.recordedTimestamp DESC, t2.id DESC
  LIMIT 1
);

මෙය පේළි 3,009,254 ක් පරීක්‍ෂා කළ අතර 5.7.21 තත්පර ~ 0.859 ක් සහ 8.0.4-rc මත තරමක් දිගු විය

උදාහරණ 2

SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue 
FROM temperature t1
INNER JOIN ( 
  SELECT max(t2.id) AS id   
  FROM temperature t2
  INNER JOIN (
    SELECT t3.groupID, max(t3.recordedTimestamp) AS recordedTimestamp
    FROM selected_group g
    INNER JOIN temperature t3 ON t3.groupID = g.id
    GROUP BY t3.groupID
  ) t4 ON t4.groupID = t2.groupID AND t4.recordedTimestamp = t2.recordedTimestamp
  GROUP BY t2.groupID
) t5 ON t5.id = t1.id;

මෙය පේළි 1,505,331 ක් පරීක්ෂා කර 5.7.21 තත්පර 1.25 ක් සහ 8.0.4-rc මත තරමක් දිගු විය

උදාහරණ 3

SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue 
FROM temperature t1
WHERE t1.id IN ( 
  SELECT max(t2.id) AS id   
  FROM temperature t2
  INNER JOIN (
    SELECT t3.groupID, max(t3.recordedTimestamp) AS recordedTimestamp
    FROM selected_group g
    INNER JOIN temperature t3 ON t3.groupID = g.id
    GROUP BY t3.groupID
  ) t4 ON t4.groupID = t2.groupID AND t4.recordedTimestamp = t2.recordedTimestamp
  GROUP BY t2.groupID
)
ORDER BY t1.groupID;

මෙය පේළි 3,009,685 ක් පරීක්ෂා කර 5.7.21 තත්පර 1.95 ක් සහ 8.0.4-rc මත තරමක් දිගු විය

උදාහරණ 4

SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue
FROM selected_group g
INNER JOIN temperature t1 ON t1.id = (
  SELECT max(t2.id)
  FROM temperature t2 
  WHERE t2.groupID = g.id AND t2.recordedTimestamp = (
      SELECT max(t3.recordedTimestamp)
      FROM temperature t3 
      WHERE t3.groupID = g.id
    )
);

මෙය පේළි 6,137,810 ක් පරීක්ෂා කළ අතර 5.7.21 තත්පර 2.2 ක් සහ 8.0.4-rc මත තරමක් දිගු විය

උදාහරණ 5

SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue
FROM (
  SELECT 
    t2.id, 
    t2.groupID, 
    t2.recordedTimestamp, 
    t2.recordedValue, 
    row_number() OVER (
      PARTITION BY t2.groupID ORDER BY t2.recordedTimestamp DESC, t2.id DESC
    ) AS rowNumber
  FROM selected_group g 
  INNER JOIN temperature t2 ON t2.groupID = g.id
) t1 WHERE t1.rowNumber = 1;

මෙය පේළි 6,017,808 ක් පරීක්ෂා කළ අතර තත්පර 8.0.4-rc සඳහා තත්පර 4.2 ක් ගතවිය

උදාහරණ 6

SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue 
FROM (
  SELECT 
    last_value(t2.id) OVER w AS id, 
    t2.groupID, 
    last_value(t2.recordedTimestamp) OVER w AS recordedTimestamp, 
    last_value(t2.recordedValue) OVER w AS recordedValue
  FROM selected_group g
  INNER JOIN temperature t2 ON t2.groupID = g.id
  WINDOW w AS (
    PARTITION BY t2.groupID 
    ORDER BY t2.recordedTimestamp, t2.id 
    RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  )
) t1
GROUP BY t1.groupID;

මෙය පේළි 6,017,908 ක් පරීක්ෂා කළ අතර තත්පර 8.0.4-rc මත තත්පර 17.5 ක් ගතවිය

උදාහරණ 7

SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue 
FROM selected_group g
INNER JOIN temperature t1 ON t1.groupID = g.id
LEFT JOIN temperature t2 
  ON t2.groupID = g.id 
  AND (
    t2.recordedTimestamp > t1.recordedTimestamp 
    OR (t2.recordedTimestamp = t1.recordedTimestamp AND t2.id > t1.id)
  )
WHERE t2.id IS NULL
ORDER BY t1.groupID;

මේ කෙනා සදහටම අරගෙන යන නිසා මට ඒක මරන්න සිද්ධ වුණා.


මෙය වෙනස් ගැටලුවකි. විසඳුම විශාල UNION සියලු විමසුමකි.
පෝල් ස්පීගල්

APaulSpiegel මම හිතන්නේ ඔබ විශාල UNION ගැන විහිළු කරනවා. තෝරාගත් කණ්ඩායම් සියල්ලම කල්තියා දැන ගැනීමට අවශ්‍ය වනු ඇති අතර, තෝරාගත් කණ්ඩායම් 2,000 ක් සමඟ ඇදහිය නොහැකි තරම් විශාල විමසුමක් වනු ඇත යන කාරණයට අමතරව, එය ඉහත වේගවත්ම උදාහරණයට වඩා දරුණු ලෙස ක්‍රියා කරනු ඇත, එබැවින් නැත, එය එසේ නොවේ විසඳුමක්.
යෝසෙප්

මම ඇත්තෙන්ම බරපතලයි. මම අතීතයේදී කණ්ඩායම් සිය ගණනක් සමඟ එය පරීක්ෂා කර ඇත්තෙමි. ඔබට විශාල කණ්ඩායම් වශයෙන් සබඳතා හැසිරවීමට අවශ්‍ය වූ විට, ප්‍රශස්ත ක්‍රියාත්මක කිරීමේ සැලැස්මක් බල කිරීම සඳහා MySQL හි ඇති එකම ක්‍රමය UNION ALL ය. SELECT DISTINCT(groupID)වේගවත් වන අතර එවැනි විමසුමක් තැනීමට අවශ්‍ය සියලු දත්ත ඔබට ලබා දෙනු ඇත. max_allowed_packetMySQL 5.7 හි 4MB ට පෙරනිමි වන විමසුම් ප්‍රමාණය ඉක්මවා නොයන තාක් කල් ඔබ හොඳින් සිටිය යුතුය .
පෝල් ස්පීගල්

5

සමූහ වාර්තාවක් අනුව අවසන් වාර්තාව ලබා ගැනීමේදී ඔබට MySQL භාවිතා කරන්නේ කෙසේදැයි අපි සොයා බලමු. උදාහරණයක් ලෙස ඔබට මෙම ප්‍රති result ල කට්ටල තිබේ නම්.

id category_id post_title

1 1 Title 1

2 1 Title 2

3 1 Title 3

4 2 Title 4

5 2 Title 5

6 3 Title 6

මාතෘකාව 3, මාතෘකාව 5 සහ මාතෘකාව 6 යන සෑම කාණ්ඩයකම අවසාන තනතුර ලබා ගැනීමට මට අවශ්‍යය. කාණ්ඩය අනුව තනතුරු ලබා ගැනීම සඳහා ඔබ යතුරු පුවරුව MySQL සමූහය භාවිතා කරනු ඇත.

select * from posts group by category_id

නමුත් මෙම විමසුමෙන් අපට ලැබෙන ප්‍රති results ල වේ.

id category_id post_title

1 1 Title 1

4 2 Title 4

6 3 Title 6

ප්‍රති by ල කට්ටලය මත කණ්ඩායම සෑම විටම කණ්ඩායමේ පළමු වාර්තාව ලබා දෙනු ඇත.

SELECT id, category_id, post_title FROM posts WHERE id IN ( SELECT MAX(id) FROM posts GROUP BY category_id );

මෙය සෑම කණ්ඩායමකම ඉහළම හැඳුනුම්පත් ඇති තනතුරු නැවත ලබා දෙනු ඇත.

id category_id post_title

3 1 Title 3

5 2 Title 5

6 3 Title 6

යොමුව මෙතැන ක්ලික් කරන්න


4
SELECT 
  column1,
  column2 
FROM
  table_name 
WHERE id IN 
  (SELECT 
    MAX(id) 
  FROM
    table_name 
  GROUP BY column1) 
ORDER BY column1 ;

ඔබේ පිළිතුර ගැන ටිකක් විස්තර කළ හැකිද? ඔබේ විමසුම විජේස් මුල් විමසුමට වඩා කැමති ඇයි?
janfoeh

4

හායි @Vijay දේව් ඔබේ මේසය නම් පණිවිඩ අඩංගු ඉඞ් ඔබගේ විමසුමට පහත ලෙස කියවිය යුතු මූලික ප්රධාන මත නවතම වාර්තාව පදනම බැරිතැන පසුව මෝටර් රථ වර්ධකයක් ප්රාථමික යතුර වන:

SELECT m1.* FROM messages m1 INNER JOIN (SELECT max(Id) as lastmsgId FROM messages GROUP BY Name) m2 ON m1.Id=m2.lastmsgId

මම සොයාගත් වේගවත්ම එක මෙයයි
CORSAIR


4

මෙන්න මගේ විසඳුම:

SELECT 
  DISTINCT NAME,
  MAX(MESSAGES) OVER(PARTITION BY NAME) MESSAGES 
FROM MESSAGE;

මෙය නමකට නවතම පණිවිඩය ලබා නොදේ. එය හුදෙක් සංකීර්ණ වූ අනුවාදයකි SELECT NAME, MAX(MESSAGES) MESSAGES FROM MESSAGE GROUP BY NAME.
පෝල් ස්පීගල්

තවද, මෙම සූත්‍රගත කිරීම තරමක් අකාර්යක්ෂම වේ.
රික් ජේම්ස්


3

මේක උත්සාහ කරන්න:

SELECT jos_categories.title AS name,
       joined .catid,
       joined .title,
       joined .introtext
FROM   jos_categories
       INNER JOIN (SELECT *
                   FROM   (SELECT `title`,
                                  catid,
                                  `created`,
                                  introtext
                           FROM   `jos_content`
                           WHERE  `sectionid` = 6
                           ORDER  BY `id` DESC) AS yes
                   GROUP  BY `yes`.`catid` DESC
                   ORDER  BY `yes`.`created` DESC) AS joined
         ON( joined.catid = jos_categories.id )  


2

වගුවක අනුපිටපත් මකා දැමීමට අපට මෙම ක්‍රමය භාවිතා කළ හැකි ක්‍රමයක් තිබේද? ප්‍රති set ල කට්ටලය මූලික වශයෙන් අද්විතීය වාර්තා එකතුවකි, එබැවින් ප්‍රති record ල කට්ටලයේ නොමැති සියලුම වාර්තා මකා දැමිය හැකි නම්, අපට effectively ලදායී ලෙස අනුපිටපත් නොමැතිද? මම මෙය උත්සාහ කළ නමුත් mySQL 1093 දෝෂයක් ලබා දුන්නා.

DELETE FROM messages WHERE id NOT IN
 (SELECT m1.id  
 FROM messages m1 LEFT JOIN messages m2  
 ON (m1.name = m2.name AND m1.id < m2.id)  
 WHERE m2.id IS NULL)

ප්‍රතිදානය තාවකාලික විචල්‍යයකට සුරැකීමට ක්‍රමයක් තිබේද? ඉන්පසු NOT IN (temp variable) වෙතින් මකා දැමිය හැකිද? Lill ඉතා ප්‍රයෝජනවත් විසඳුමක් සඳහා ස්තූතියි.

සංස්කරණය කරන්න: මම විසඳුම සොයා ගත්තා යැයි සිතන්න:

DROP TABLE IF EXISTS UniqueIDs; 
CREATE Temporary table UniqueIDs (id Int(11)); 

INSERT INTO UniqueIDs 
    (SELECT T1.ID FROM Table T1 LEFT JOIN Table T2 ON 
    (T1.Field1 = T2.Field1 AND T1.Field2 = T2.Field2 #Comparison Fields  
    AND T1.ID < T2.ID) 
    WHERE T2.ID IS NULL); 

DELETE FROM Table WHERE id NOT IN (SELECT ID FROM UniqueIDs);

2

ඔබගේ ප්‍රශ්නයට අනුව පහත විමසුම හොඳින් ක්‍රියාත්මක වේ.

SELECT M1.* 
FROM MESSAGES M1,
(
 SELECT SUBSTR(Others_data,1,2),MAX(Others_data) AS Max_Others_data
 FROM MESSAGES
 GROUP BY 1
) M2
WHERE M1.Others_data = M2.Max_Others_data
ORDER BY Others_data;

2

ඔබ එක් එක් කිරීම සඳහා පසුගිය පේළිය අවශ්ය නම් Name, ඔබ පේලියට සංඛ්යාව එක් එක් පේළිය කණ්ඩායමට විසින් ලබා දිය හැක Nameවිසින් හා සාමය Idඅවරෝහණ ක්රමයට.

ප්‍රශ්නය

SELECT t1.Id, 
       t1.Name, 
       t1.Other_Columns
FROM 
(
     SELECT Id, 
            Name, 
            Other_Columns,
    (
        CASE Name WHEN @curA 
        THEN @curRow := @curRow + 1 
        ELSE @curRow := 1 AND @curA := Name END 
    ) + 1 AS rn 
    FROM messages t, 
    (SELECT @curRow := 0, @curA := '') r 
    ORDER BY Name,Id DESC 
)t1
WHERE t1.rn = 1
ORDER BY t1.Id;

SQL Fiddle


2

කොහොමද මේ:

SELECT DISTINCT ON (name) *
FROM messages
ORDER BY name, id DESC;

මට සමාන ගැටළුවක් (postgresql දැඩි මත) සහ 1M වාර්තා වගුවක තිබුණි. මෙම විසඳුම LEFT JOIN සමඟ නිපදවන 1.7s vs 44s ගනී. මගේ නඩුවේදී, ඔබගේ නම ක්ෂේත්‍රයේ අනුරූපය NULL අගයන්ට එරෙහිව පෙරීමට මට සිදු විය, එහි ප්‍රති sec ලයක් ලෙස තත්පර 0.2 කින් ඊටත් වඩා හොඳ කාර්ය සාධනයක් ලැබෙනු ඇත.


1

කාර්ය සාධනය සැබවින්ම ඔබේ සැලකිල්ල නම්, ඔබට මේසය මත IsLastInGroupBIT වර්ගයේ නව තීරුවක් හඳුන්වා දිය හැකිය .

අන්තිම තීරු වල එය සත්‍ය ලෙස සකසා සෑම පේළියක්ම ඇතුළු කිරීම / යාවත්කාලීන කිරීම / මකා දැමීම සමඟ එය නඩත්තු කරන්න. ලිවීම් මන්දගාමී වනු ඇත, නමුත් ඔබට කියවීම් වලින් ප්‍රතිලාභ ලැබේ. එය ඔබගේ භාවිත අවස්ථාව මත රඳා පවතින අතර මම එය නිර්දේශ කරන්නේ ඔබ කියවා-අවධානය යොමු කර ඇත්නම් පමණි.

එබැවින් ඔබේ විමසුම මෙසේ වනු ඇත:

SELECT * FROM Messages WHERE IsLastInGroup = 1

මූඩ්ල් හි සමහර වගු වල මේ ආකාරයේ ධජ තීරුවක් ඇත.
ලෝරන්ස්

1

තවත් ප්‍රවේශයක්:

එක් එක් වැඩසටහන සමඟ උපරිම m2_price සමඟ නිසි දේ සොයා ගන්න (1 වැඩසටහනක n ගුණාංග):

select * from properties p
join (
    select max(m2_price) as max_price 
    from properties 
    group by program_id
) p2 on (p.program_id = p2.program_id)
having p.m2_price = max_price

"කොහේද" නොව "තිබීම" භාවිතා කිරීම නිවැරදිද?
ඇන්සල්මෝ පාක්


0

ඔබට ගණන් කිරීමෙන් කණ්ඩායම්ගත කළ හැකි අතර කණ්ඩායමේ අවසාන අයිතමයද ලබා ගත හැකිය:

SELECT 
    user,
    COUNT(user) AS count,
    MAX(id) as last
FROM request 
GROUP BY user

0

ඔරකල් විමසුමට පහළින් ඇති බලාපොරොත්තුව උපකාරී වේ:

WITH Temp_table AS
(
    Select id, name, othercolumns, ROW_NUMBER() over (PARTITION BY name ORDER BY ID 
    desc)as rank from messages
)
Select id, name,othercolumns from Temp_table where rank=1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.