Postgres:異なるが1列のみ


120

名前(1 mio。行を超える)を持つpgsqlのテーブルがありますが、重複も多数あります。私は3つのフィールドを選択:idnamemetadata

私はランダムに選択するようにしたいORDER BY RANDOM()LIMIT 1000私は、これは私のPHPスクリプトで、いくつかのメモリを節約するために多くの手順で行います。

しかし、どうすればそれができるので、名前が重複していないリストのみが表示されます。

たとえば、[1,"Michael Fox","2003-03-03,34,M,4545"]返されますが、返されません[2,"Michael Fox","1989-02-23,M,5633"]。名前フィールドは最も重要であり、selectを実行するたびにリスト内で一意である必要があり、ランダムである必要があります。

私はGROUP BY namebu を試してみましたが、idとメタデータがGROUP BY同様にまたはaggragate関数にあると想定していますが、何らかの方法でそれらをフィルタリングしたくありません。

誰もが多くの列をフェッチする方法を知っていますが、1つの列でのみ区別しますか?

回答:


225

1つ(またはn)列のみを区別するには:

select distinct on (name)
    name, col1, col2
from names

これにより、名前を含むすべての行が返されます。返される行を制御する場合は、次のように注文する必要があります。

select distinct on (name)
    name, col1, col2
from names
order by name, col1

col1で注文すると、最初の行が返されます。

distinct on

SELECT DISTINCT ON(expression [、...])は、指定された式が等しいと評価される行の各セットの最初の行のみを保持します。DISTINCT ON式は、ORDER BYと同じ規則を使用して解釈されます(上記を参照)。ORDER BYを使用して目的の行が最初に表示されるようにしない限り、各セットの「最初の行」は予測できないことに注意してください。

DISTINCT ON式は、左端のORDER BY式と一致する必要があります。ORDER BY句には通常、各DISTINCT ONグループ内の行の優先順位を決定する追加の式が含まれます。


注文で良いキャッチ。ランダムな順序付けが必要だと彼らが言ったので、私はそれを含めませんでしたが、とにかく言及することが重要です。
クレイグリンガー2013年

されるorder by name必要?それは別の結果を生み出しorder by col1ますか?
エリオットチャンス

1
@elliot yes nameが必要です。distinct onマニュアルで確認してください。
Clodoaldo Neto 2015

1
TSQLチームがこれを行うこのような賢明な方法を提供できればと思います。
JTW 2015年


17

誰もが多くの列をフェッチする方法を知っていますが、1つの列でのみ区別しますか?

あなたDISTINCT ONが欲しい。

サンプルデータまたは完全なクエリを提供していないため、表示するものはありません。あなたは次のようなものを書きたいです:

SELECT DISTINCT ON (name) fields, id, name, metadata FROM the_table;

これにより、予測できない(「ランダム」ではない)行のセットが返されます。予測可能にしたい場合は、ORDER BYClodaldoごとの回答を追加してください。本当にランダムにしたい場合は、そうする必要がありますORDER BY random()


このDISTINCT ON句を使用すると、同じものをORDER BYすることだけができることに注意してください。したがって、DISTINCT ON(名前)と言った場合は、他に何でも好きな名前で並べ替える必要があります。ほとんど理想的ではありません。
Kevin Parker

ケビン、外部クエリでCTEまたはFROMのサブクエリとORDER BYを使用することができます
Craig Ringer

はい、そしてパフォーマンスが進むのを観察します...インデックススペースから可能なすべての結果が検索されます。それは何になります可能性があり posgresが異なることにより、明確な/順序を扱うことができないという理由だけで900ms一つに右のインデックスと10-20msクエリなります。外部クエリの順序が何であっても関係ありません。内部サブクエリのインデックスを使用して、最初に一致するものを見つけ、次に再ソートします。ハッピーで私たちの問題の真の解決策のためのコンサルティング料を行うにはdba.stackexchange.com/questions/260852/...
ケビン・パーカー

4
SELECT NAME,MAX(ID) as ID,MAX(METADATA) as METADATA 
from SOMETABLE
GROUP BY NAME

2
注意してください:「一緒」に属するID値またはメタデータ値を返さない可能性があります
a_horse_with_no_name

@Novumいいえ。これは、猫がMichaelの行の1つからid値を取得し、Michaelの最大値を要求されたときに別の行からメタデータを取得することを意味します。
Clodoaldo Neto 2013年

そうですね、それはOPが使用する実際のデータに大きく依存します。MINなどを使用する必要がある場合があります。実例として、GROUP BY句にないフィールドを含める方法を説明しました。
David Jashi

異なる行の異なる値が混同されるため、これは良い解決策ではありません。
Elliot Chance
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.