6

テーブル内の重複を見つける必要があります。MySQL では、単純に次のように記述します。

SELECT *,count(id) count FROM `MY_TABLE`
GROUP BY SOME_COLUMN ORDER BY count DESC

このクエリはうまくいきます:

  • SOME_COLUMN に基づいて重複を検索し、繰り返し回数を指定します。
  • 繰り返しの降順でソートします。これは、主要な重複をすばやくスキャンするのに役立ちます。
  • 残りのすべての列にランダムな値を選択して、それらの列の値を把握します。

Postgres で同様のクエリを実行すると、次のエラーが表示されます。

列「MY_TABLE.SOME_COLUMN」は、GROUP BY 句に指定するか、集計関数で使用する必要があります

このクエリに相当する Postgres は何ですか?

PS: MySQL の動作が SQL 標準から逸脱していることは知っています。

4

4 に答える 4

12

バックティックは非標準の MySQL です。正規の二重引用符を使用して識別子を引用します (MySQL でも可能です)。つまり、実際にテーブルに名前が付けられている"MY_TABLE"場合 (すべて大文字)。(より賢明に)名前を付けた場合my_table(すべて小文字)、二重引用符を削除するか、小文字を使用できます。

また、関数名を識別子として使用するのは悪い習慣であるため、ct代わりにas エイリアスを使用します。count

シンプルなケース

これは PostgreSQL 9.1で動作します:

SELECT *, count(id) ct
FROM   my_table
GROUP  BY primary_key_column(s)
ORDER  BY ct DESC;

GROUP BY句に主キー列が必要です。結果はMySQL クエリと同じですctが、常に 1 (または の場合は 0 id IS NULL) になり、重複を見つけるのには役に立ちません。

主キー列以外でグループ化

他の列でグループ化する場合は、さらに複雑になります。このクエリは、MySQL クエリの動作を模倣しており*.

SELECT DISTINCT ON (1, some_column)
       count(*) OVER (PARTITION BY some_column) AS ct
      ,*
FROM   my_table
ORDER  BY 1 DESC, some_column, id, col1;

これは、 (SQL-Standard) のDISTINCT ONように (PostgreSQL 固有)がウィンドウ関数のに適用されるため機能します。ウィンドウ関数(句付き) には PostgreSQL 8.4以降が必要であり、MySQL では使用できません。DISTINCTcount(*) OVER (...)OVER

主制約または一意制約に関係なく、任意のテーブルで機能します。

1in DISTINCT ONandは、リストORDER BY内のアイテムの序数を参照するための省略形です。SELECT

SQL Fiddleを使用して、両方を並べて示します。

この密接に関連する回答の詳細:


count(*)対。count(id)

重複を探している場合は、 を使用するcount(*)よりも使用する方が適していcount(id)ます。idif can beには微妙な違いがあります。これは、値がカウントされないNULLためNULLです - whilecount(*)はすべての行をカウントします。idが定義されている場合NOT NULL、結果は同じですが、count(*)一般的にはより適切です (また、わずかに高速です)。

于 2012-05-01T13:44:16.110 に答える
3

DISTINCT ON を使用する別のアプローチを次に示します。

select 

  distinct on(ct, some_column) 

  *,
  count(id) over(PARTITION BY some_column) as ct

from my_table x
order by ct desc, some_column, id

情報源:

CREATE TABLE my_table (some_column int, id int, col1 int);

INSERT INTO my_table  VALUES
 (1, 3,  4)
,(2, 4,  1)
,(2, 5,  1)
,(3, 6,  4)
,(3, 7,  3)
,(4, 8,  3)
,(4, 9,  4)
,(5, 10, 1)
,(5, 11, 2)
,(5, 11, 3);

出力:

SOME_COLUMN ID          COL1        CT
5           10          1           3
2           4           1           2
3           6           4           2
4           8           3           2
1           3           4           1

ライブ テスト: http://www.sqlfiddle.com/#!1/e2509/1

DISTINCT ON ドキュメント: http://www.postgresonline.com/journal/archives/4-Using-Distinct-ON-to-return-newest-order-for-each-customer.html

于 2012-05-03T00:01:27.610 に答える
1

これは自己結合された CTE で、 を使用できますselect *。key0 は意図した一意のキーです。{key1,key2} は、現在一意でない行に対処するために必要な追加のキー要素です。YMMV、自己責任で使用してください。

WITH zcte AS (
        SELECT DISTINCT tt.key0
        , MIN(tt.key1) AS key1
        , MIN(tt.key2) AS key2
        , COUNT(*) AS cnt
        FROM ztable tt
        GROUP BY tt.key0
        HAVING COUNT(*) > 1
        )
SELECT zt.*
        , zc.cnt AS cnt
FROM ztable zt
JOIN zcte zc ON zc.key0 = zt.key0 AND zc.key1 =  zt.key1 AND zc.key2 = zt.key2
ORDER BY zt.key0, zt.key1,zt.key2
      ;

ところで:OPの意図した動作を得るには、HAVING COUNT(*) > 1句を省略してください。

于 2012-05-01T15:08:18.360 に答える
1

mysql では、グループ化された列の一意の組み合わせごとに見つかった最初の行を返すことによって、集計されていない選択された列をリストgroup byから除外できます。これは非標準の SQL 動作です。group by

一方、postgres は SQL 標準に準拠しています。

postgres には同等のクエリはありません。

于 2012-05-01T13:45:15.027 に答える