私は3つのフィールドを持つテーブルを持っています:
id
note
created_at
SQL言語、特にPostgresで最後の値を選択するnote
必要なく選択できる方法はありますLIMIT 1
か?
通常のクエリ:
select note from table order by created_at desc limit 1
サブクエリとして必要になるため、制限を回避することに興味があります。
私は3つのフィールドを持つテーブルを持っています:
id
note
created_at
SQL言語、特にPostgresで最後の値を選択するnote
必要なく選択できる方法はありますLIMIT 1
か?
通常のクエリ:
select note from table order by created_at desc limit 1
サブクエリとして必要になるため、制限を回避することに興味があります。
SELECT note FROM tbl t
WHERE NOT EXISTS
(SELECT 1 FROM tbl t1 WHERE t1.created_at > t.created_at);
「後で他のメモが作成されていないメモを見つけます。」
これは、@ Ollieがすでに指摘したように、そうでない場合に複数の行を返すことができるという@Hoganのバージョンの弱点を共有しています。@Hogan のクエリ (単純な型に対してのみ定義されている) とは異なり、これは簡単に改善できます。created_at
UNIQUE
max()
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_at
、id
が主キーであり、したがって一意です。これは PostgreSQL と MySQL で機能します。
同じことが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
。
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 で立ち往生しています。
私はPostgresを100%使用していません(実際には使用したことがありません)が、次のようなもので同じ効果を得ることができます-created_at
が一意である場合...(または一意の列で):
SELECT note FROM table WHERE created_at = (
SELECT MAX(created_at) FROM table
)