18

テーブル:

(`post_id`, `forum_id`, `topic_id`, `post_time`) 
(79, 8, 4, '2012-11-19 06:58:08');
(80, 3, 3, '2012-11-19 06:58:42'),
(81, 9, 9, '2012-11-19 06:59:04'),
(82, 11, 6, '2012-11-19 16:05:39'),
(83, 9, 9, '2012-11-19 16:07:46'),
(84, 9, 11, '2012-11-19 16:09:33'),

クエリ:

SELECT  post_id, forum_id, topic_id FROM posts 
GROUP BY topic_id 
ORDER BY post_time DESC
LIMIT 5

結果:

[0] => [post_id] => 84 [forum_id] => 9 [topic_id] => 11  
[1] => [post_id] => 82 [forum_id] => 11 [topic_id] => 6  
[2] => [post_id] => 81 [forum_id] => 9 [topic_id] => 9  
[3] => [post_id] => 80 [forum_id] => 3 [topic_id] => 3  
[4] => [post_id] => 79 [forum_id] => 8 [topic_id] => 4

問題:

post_id -> 81 の代わりに post_id -> 83 を返すようにクエリを書き直す方法は?

どちらも同じフォーラム ID とトピック ID を持っていますが、post_id -> 81 は post_id -> 83 より古い日付です。

しかし、Group By は「最新の」レコードではなく「最初の」レコードを取得するようです。

クエリを次のように変更してみました

SELECT  post_id, forum_id, topic_id, MAX(post_time)

しかし、それはpost_id 81と83の両方を返します

4

5 に答える 5

27

グループ句で使用されておらず、集計でもない属性を選択した場合、結果は指定されません。つまり、他の属性がどの行から選択されているかわかりません。(SQL 標準ではこのようなクエリは許可されていませんが、MySQL はより緩和されています)。

次に、クエリは次のように記述します。

SELECT post_id, forum_id, topic_id
FROM posts p
WHERE post_time =
  (SELECT max(post_time) FROM posts p2
   WHERE p2.topic_id = p.topic_id
   AND p2.forum_id = p.forum_id)
GROUP BY forum_id, topic_id, post_id
ORDER BY post_time DESC
LIMIT 5;

また

SELECT post_id, forum_id, topic_id FROM posts
NATURAL JOIN
(SELECT forum_id, topic_id, max(post_time) AS post_time
 FROM posts
 GROUP BY forum_id, topic_id) p
ORDER BY post_time
LIMIT 5;
于 2012-11-19T19:12:38.447 に答える
12

あまり美しくはありませんが、機能します:

SELECT * FROM (SELECT  post_id, forum_id, topic_id FROM posts
ORDER BY post_time DESC) as temp
GROUP BY topic_id
于 2012-11-19T18:15:27.397 に答える
4

のようなものを試してください

SELECT post_id, forum_id, topic_id 
FROM   (SELECT post_id, forum_id, topic_id
        FROM posts
        ORDER BY post_time DESC) 
GROUP BY topic_id 
ORDER BY topic_id desc
LIMIT 0,5

order byとを必要に応じて変更limitします。

于 2012-11-19T18:15:36.633 に答える
0

おそらく最良の方法ではないかもしれませんが、関数group_concat()がユーザーフルになる場合があります。これは、必要に応じて並べ替えられ、コンマで区切られたすべての集計値の文字列を返します (結合された値はスペースで区切られます)。次に、関数 SPLIT_STRING() を使用して、文字列の最初の ID を切り取ります。

SELECT  
post_id, 
SPLIT_STRING( group_concat( forum_id, post_time ORDER BY post_time DESC ) ,' ',1 )as forum_id, 
SPLIT_STRING( group_concat( topic_id, post_time ORDER BY post_time DESC ) ,' ',1 )as topic_id ,
FROM posts 
GROUP BY topic_id 
ORDER BY post_time DESC
LIMIT 5

したがって、集計された forum_id、post_time は次のようになります。

81 2012-11-19 06:59:04,83 2012-11-19 16:07:46

したがって、整数と日時の組み合わせの文字列表現を操作する必要があり、各組み合わせはコンマで区切られているため、この関数を使用して最初の INT を取得しました。

CREATE FUNCTION SPLIT_STRING(str VARCHAR(255), delim VARCHAR(12), pos INT)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
       LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1),
       delim, '');

注 : 関数 SPLIT_STRING(str, delim, pos) はここで見つかりました: MySQL で文字列を操作するのは、explode() と同等です

于 2015-05-28T19:06:43.950 に答える