回答:
SELECT DISTINCT a,b,c FROM t
あるおよそに相当:
SELECT a,b,c FROM t GROUP BY a,b,c
より強力なため、GROUP BY構文に慣れることをお勧めします。
あなたのクエリのために、私はこのようにします:
UPDATE sales
SET status='ACTIVE'
WHERE id IN
(
SELECT id
FROM sales S
INNER JOIN
(
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING COUNT(*) = 1
) T
ON S.saleprice=T.saleprice AND s.saledate=T.saledate
)
これまでの回答をまとめ、整理して改善すると、次の優れたクエリに到達します。
UPDATE sales
SET status = 'ACTIVE'
WHERE (saleprice, saledate) IN (
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING count(*) = 1
);
どちらよりもはるかに高速です。現在受け入れられている回答のパフォーマンスを10〜15倍にします(PostgreSQL 8.4および9.1での私のテストでは)。
しかし、これはまだ最適とはほど遠いです。NOT EXISTS
(反)セミ結合を使用すると、パフォーマンスがさらに向上します。EXISTS
標準SQLであり、永遠に(少なくともPostgreSQL 7.2以降、この質問がされる前に)提示された要件に完全に適合しています。
UPDATE sales s
SET status = 'ACTIVE'
WHERE NOT EXISTS (
SELECT FROM sales s1 -- SELECT list can be empty for EXISTS
WHERE s.saleprice = s1.saleprice
AND s.saledate = s1.saledate
AND s.id <> s1.id -- except for row itself
)
AND s.status IS DISTINCT FROM 'ACTIVE'; -- avoid empty updates. see below
db <> fiddle here
古いSQL Fiddle
(id
例のように)テーブルの主キーまたは一意のキーctid
がない場合は、このクエリの目的で(他の目的ではなく)システム列で置き換えることができます。
AND s1.ctid <> s.ctid
すべてのテーブルには主キーが必要です。まだない場合は追加してください。Postgres 10 serial
以降では、またはのIDENTITY
列をお勧めします。
関連:
EXISTS
反準結合のサブクエリは、最初の重複が見つかるとすぐに評価を停止する可能性があります(これ以上調べても意味がありません)。重複の少ないベーステーブルの場合、これは少し効率的です。たくさんの複製があると、これはずっと効率的になります。
すでにstatus = 'ACTIVE'
この更新が適用されている行の場合、何も変更されませんが、新しい行バージョンが完全なコストで挿入されます(マイナーな例外が適用されます)。通常、これは必要ありません。WHERE
これを回避し、さらに高速にするために、上記で示したような別の条件を追加します。
status
が定義されている場合NOT NULL
、次のように簡略化できます。
AND status <> 'ACTIVE';
列のデータ型は<>
演算子をサポートする必要があります。一部のタイプはjson
しないでください。見る:
このクエリは(Joelが現在受け付けている回答とは異なり)、NULL値を等しいものとして扱いません。次の2つの行は(saleprice, saledate)
、「人間の目と同じに見えますが」「明確」と見なされます。
(123, NULL)
(123, NULL)
また、NULL値はSQL標準に従って等しいと比較されないため、一意のインデックスなど、ほとんどどこでも渡します。見る:
大藤、GROUP BY
、DISTINCT
またはDISTINCT ON ()
同等として扱うのNULL値。目的に応じて適切なクエリスタイルを使用します。NULL比較を同等にするために、一部またはすべての比較のIS NOT DISTINCT FROM
代わりにこの高速クエリを引き続き使用でき=
ます。もっと:
比較されるすべての列が定義されている場合NOT NULL
、意見の不一致の余地はありません。
count(*)
はより効率的ですcount(<expression>)
。やってみなよ。Postgresは、集約関数のこのバリアントをより高速に実装しています。多分あなたは他のいくつかのRDBMSとPostgresを混同していますか?
クエリの問題は、GROUP BY句を使用する場合(基本的に、distinctを使用して行います)、グループ化した列または関数を集計した列しか使用できないことです。値が異なる可能性があるため、列IDを使用できません。あなたの場合、HAVING句のために常に1つの値しかありませんが、ほとんどのRDBMSはそれを認識するのに十分スマートではありません。
ただし、これは機能するはずです(結合は必要ありません)。
UPDATE sales
SET status='ACTIVE'
WHERE id IN (
SELECT MIN(id) FROM sales
GROUP BY saleprice, saledate
HAVING COUNT(id) = 1
)
MINの代わりにMAXまたはAVGを使用することもできます。一致する行が1つしかない場合は、列の値を返す関数を使用することが重要です。
1つの列「GrondOfLucht」から個別の値を選択したいのですが、「sortering」列に指定された順序で並べ替える必要があります。を使用して1つの列だけの個別の値を取得することはできません
Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering
また、「sortering」列も提供します。「GrondOfLucht」と「sortering」は一意ではないため、結果はすべての行になります。
GROUPを使用して、「sorting」で指定された順序で「GrondOfLucht」のレコードを選択します
SELECT GrondOfLucht
FROM dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)
次のように、DBMSが複数の列を持つDISTINCTをサポートしていない場合:
select distinct(col1, col2) from table
一般に、複数選択は次のように安全に実行できます。
select distinct * from (select col1, col2 from table ) as x
これはほとんどのDBMSで機能し、グループ化機能を回避しているため、ソリューションごとのグループ化よりも高速であることが期待されています。