web-dev-qa-db-ja.com

列の最大値+グループ化に基づいてMySQLから行を選択する方法

ユーザーが特定のWebページを常に表示している(たとえば)テーブルがあります。もちろん、ユーザーはページを複数回見ることができるため、次のように、ユーザーとページに複数のエントリが存在する可能性があります。

nid     time    user  page_id
 25     8000       4      467
 24     7000       1      482
 23     6000       1      484
 22     5000       1      482
 21     4000       5      467
 20     3000       4      467

すべてのユーザーが閲覧したすべてのページに対応する行を返すクエリを実行したいのですが、ユーザーがページを複数回閲覧した場合、最新のビューに対応する行を取得します(つまり、時間)。したがって、私はこれを取得する必要があります:

nid     time    user  page_id
 25     8000       4      467
 24     7000       1      482
 23     6000       1      484
 21     4000       5      467

ユーザー1が後で482ページを見たため、行22が失われ、ユーザー4が後でページ467を見たため、行20が失われます。

私はこれをほぼ理解しましたが、それを完全に解読することはできません。また、テストケースの偶然ではなく、得られる結果は一般的に正しいと確信しています。 GROUP BYまたはDISTINCTクエリと埋め込みクエリの間を行き来し続けると、脳が爆発します。助言がありますか?ありがとう!

14
Jim Miller

行全体が必要な場合は、次を使用できます。

SELECT fullTable.nid as nid, 
       recent.time as time, 
       fullTable.user as user, 
       fullTable.page_id as page_id 
  FROM TableName fullTable 
         INNER JOIN   (SELECT MAX(t1.time) as time, t1.user, t1.page_id 
                         FROM TableName t1 
                     GROUP BY user, page_id) recent
                 ON recent.time = fullTable.time AND 
                    recent.user = fullTable.user AND 
                    recent.page_id = fullTable.page_id
ORDER BY time DESC

「groupby」句の外側の列を要求した場合、mysqlはこのグループ内のこの列の任意の値を返すことができます。したがって、グループ内のすべての値が同じでない場合、つまりその場合、select句に直接含めることはできず、結合を使用する必要があります。

MySQLでグループ化されていない列の詳細については、 参照 を参照してください。

Nidフィールドが必要ない場合は、次のものを使用できます。

SELECT MAX(time) as time, user, page_id 
  FROM TableName
GROUP BY user, page_id
ORDER BY time DESC
20
Borja

これを試して:

SELECT *
  FROM <YOUR_TABLE>
 WHERE (user, page_id, time) IN
    (
    SELECT  user, page_id, MAX(time) time
      FROM <YOUR_TABLE>
    GROUP BY user, page_id
   )
1
Chandu
SELECT nid, MAX(time), user, page_id 
FROM TableName 
GROUP BY nid, user, page_id
0
nybbler