18

PostgreSQL では、すべてのユーザーを一度に取得し、日付順に並べ替えたいと考えています。

これは私のクエリです:

SELECT id, useridx, isread, message, date
  FROM messages
 WHERE isread = 1
 GROUP BY useridx
 ORDER BY date DESC

これはサンプルデータです:

------------------------------------------------------
+  id  |  useridx |  isread  |  messsage |  date     +
------------------------------------------------------
   1   |  1       |  0        | Hello    |  2012-01-01    
   2   |  2       |  1        | Hi       |  2012-01-02    
   3   |  3       |  1        | Test     |  2012-01-03    
   4   |  3       |  0        | My Msg   |  2012-01-04    
   5   |  4       |  1        | sadasd   |  2012-01-05    
   6   |  4       |  1        | sdfsdfd  |  2012-01-06    
   7   |  4       |  0        | sdfsdfsd |  2012-01-07    
   8   |  5       |  0        | 5345634  |  2012-01-08
   9   |  6       |  0        | sdfdfsd  |  2012-01-09
   10  |  7       |  0        | sdfsdfsf |  2012-01-10
------------------------------------------------------

今、私がやりたいことは、useridx と日付順でグループ化して、このテーブルを取得することです。

期待される結果:

------------------------------------------------------
+  id  |  useridx |  isread  |  messsage |  date     +
------------------------------------------------------  
   6   |  4       |  1        | sdfsdfd  |  2012-01-06 
   3   |  3       |  1        | Test     |  2012-01-03  
   2   |  2       |  1        | Hi       |  2012-01-02    
------------------------------------------------------

実結果

ERROR:  column "messages.date" must appear in the GROUP BY clause or be used in an aggregate function

グループデートもしたくない。useridx でグループ化し、日付 DESC で並べ替えたいだけです。

どんな助け/アイデアも大歓迎です!

注:Distinctも試しました。私のニーズに合わないか、間違っていました。

私は非常に混乱しており、メソッドとメソッドの間で立ち往生しています。DISTINCT ONrank()

結論:ここで同じ問題を抱えている人は、これを答えとして読むことができます. @kgrittn と @mu is too short の両方の答えは正しいです。私は自分のプロジェクトで回答とスキーマの両方を引き続き使用しますが、そのうちにどちらが最適かを理解できるようになります。したがって、それらのいずれかを選択して、作業を続けてください。あなたは大丈夫です。

Last Update : Distinct On が一部の ID を結果から除外することがあります。id列があり、同じ6行あるとしましょう。したがって、結果から除外すると区別されますが、rank() は単に結果になります。したがって、rank() を使用してください。

4

5 に答える 5

12

PostgreSQL は、MySQL とは異なり、集計クエリで集計されていない列のランダム データを表示しません。

解決策はエラーメッセージにあります

ERROR:  column "messages.date" must appear in the GROUP BY clause or be used in an aggregate function

つまり、「messages.date」列を GROUP BY するか、この列を選択するときに MIN() や MAX() などの集計関数を使用する必要があります

例:

SELECT MIN(id), useridx, isread, message, MAX(date)
FROM messages WHERE isread = 1 
GROUP BY useridx, isread, message
ORDER BY MAX(date) DESC
于 2012-04-26T22:56:54.977 に答える
10

rank()ウィンドウ関数を使用して各useridxグループ内の結果を並べ替え、ランク付けされた結果を派生テーブルにラップして最初の結果を剥がします。

select id, useridx, isread, message, date
from (
    select id, useridx, isread, message, date,
           rank() over (partition by useridx order by date desc) as r
    from messages
    where isread = 1
) as dt
where r = 1

idこれにより、サンプルから 2、3、および 6の行が得られます。over同じ日に複数のメッセージがある場合に一貫して選択できるように、 にセカンダリ ソート キーを追加することをお勧めしuseridxます。

ウィンドウ関数を使用するには、少なくとも PostgreSQL 8.4 (AFAIK) が必要です。

于 2012-04-26T23:25:17.297 に答える
5

別のオプションを使用することSELECT DISTINCT ONです (これは単純な とは大きく異なりますSELECT DISTINCT):

SELECT *
  FROM (SELECT DISTINCT ON (useridx)
            id, useridx, isread, message, date
          FROM messages
          WHERE isread = 1
          ORDER BY useridx, date DESC) x
  ORDER BY date DESC;

場合によっては、これは他のアプローチよりもうまくスケーリングできます。

于 2012-04-27T12:21:49.230 に答える
3

数年後ですが、FROM サブクエリで注文することはできません。

SELECT m.id, m.useridx, m.isread, m.message, m.date
FROM (
   SELECT m2.id, m2.useridx, m2.isread, m2.message, m2.date 
   FROM message m2 
   ORDER BY m2.id ASC, m2.date DESC
) m
WHERE isread = 1
GROUP BY useridx

これはPostgreSQL 9.2で機能します

于 2016-08-26T08:29:41.130 に答える
2

結果を集計しています。

これは、ユーザーの2行ではなく、31行だけになることを意味します。ただし、集約された行にはid、、、列も選択します 。PostgreSQLはこのデータをどのように配信することになっていますか?それは可能な値である必要がありますか?多分?messageisreadmax()min()

最新のメッセージに関するデータが必要だと思います。このクエリを試してください:

SELECT id, useridx, isread, message, date FROM messages
 WHERE isread = 1 AND (useridx, date) IN
  (SELECT useridx, max(date) FROM messages WHERE isread = 1 GROUP BY useridx);
于 2012-04-26T22:34:34.660 に答える