3

私は3つのフィールドを持つテーブルを持っています:

id
note
created_at

SQL言語、特にPostgresで最後の値を選択するnote必要なく選択できる方法はありますLIMIT 1か?

通常のクエリ:

select note from table order by created_at desc limit 1

サブクエリとして必要になるため、制限を回避することに興味があります。

4

4 に答える 4

7

EXISTS semi-joinを使用した単純なバージョン:

SELECT note FROM tbl t
WHERE  NOT EXISTS
    (SELECT 1 FROM tbl t1 WHERE t1.created_at > t.created_at);

「後で他のメモが作成されていないメモを見つけます。」

これは、@ Ollieがすでに指摘したように、そうでない場合に複数の行を返すことができるという@Hoganのバージョンの弱点を共有しています。@Hogan のクエリ (単純な型に対してのみ定義されている) とは異なり、これは簡単に改善できます。created_atUNIQUEmax()

行の種類を比較する

SELECT note FROM tbl t
WHERE  NOT EXISTS
   (SELECT 1 FROM tbl t1
    WHERE  (t1.created_at, t1.id) > (t.created_at, t.id));

idと同点の場合に最大のものを求めていると仮定するとcreated_atidが主キーであり、したがって一意です。これは PostgreSQL と MySQL で機能します。

SQL フィドル。

ウィンドウ関数

同じことがPostgreSQLのウィンドウ関数で実現できます。

SELECT note
FROM  (
    SELECT note, row_number() OVER (ORDER BY created_at DESC, id DESC) AS rn
    FROM   tbl t 
    ) x
WHERE  rn = 1;

MySQLはウィンドウ関数をサポートしていません。次のような変数に置き換えることができます。

SELECT note
FROM  (
    SELECT note, @rownum := @rownum + 1 AS rn
    FROM   tbl t 
         ,(SELECT @rownum := 0) r
    ORDER  BY created_at DESC, id DESC
    ) x
WHERE  rn = 1;

(SELECT @rownum := 0) r明示的なコマンドなしで変数を 0 で初期化しますSET

SQL フィドル。

于 2012-08-25T01:18:29.543 に答える
3

id 列が自動インクリメントの主キー フィールドである場合、それは非常に簡単です。これは、最新のメモの ID が最も高いと想定しています。(それは真実ではないかもしれません。あなただけがそれを知っています!)

select *
  from note
 where id = (select max(id) from note)

ここにあります: MySQLの場合はhttp://sqlfiddle.com/#!2/7478a/1/0、postgreSQLの場合はhttp://sqlfiddle.com/#!1/6597d/1/0です。同じSQL。

id 列が設定されていないため、最新のメモの id が最大であるが、依然として主キーである (つまり、各行に一意の値がある) 場合、少し難しくなります。同一の日付を明確にする必要があります。これは、最も高い ID を任意に選択することによって行います。

select *
  from note
  where id = (
              select max(id)
                from note where created_at = 
                   (select max(created_at) 
                      from note
                   )
              )

例を次に示します。MySQLの場合はhttp://sqlfiddle.com/#!2/1f802/4/0です。これはpostgreSQL用です(SQLは同じです、イェイ!)http://sqlfiddle.com/#!1/bca8c/1/0

別の可能性: 両方のメモがまったく同時に作成された場合、両方のメモを 1 行にまとめて表示したい場合があります。繰り返しますが、それはあなただけが知っています。

select group_concat(note separator '; ') 
  from note 
 where created_at = (select max(created_at) from note)

postgreSQL 9 以降では、

 select string_agg(note, '; ') 
   from note 
  where created_at = (select max(created_at) from note)

重複する created_at 時間と重複する id 値の可能性があり、group_concat 効果が必要ない場合は、残念ながら LIMIT で立ち往生しています。

于 2012-08-24T23:22:16.297 に答える
2

私はPostgresを100%使用していません(実際には使用したことがありません)が、次のようなもので同じ効果を得ることができます-created_atが一意である場合...(または一意の列で):

SELECT note FROM table WHERE created_at = (
    SELECT MAX(created_at) FROM table
)
于 2012-08-24T22:21:33.127 に答える