Back-ticks are a non-standard MySQL thing. Use canonical double quotes to quote identifiers (perhaps in MySQL too). That is, if your table is actually called "MY_TABLE"
(all uppercase). If you (more sensibly) called it my_table
(all lowercase letters), you can remove double quotes or use lowercase letters.
In addition, I use ct
instead of count
as an alias because it is bad practice to use function names as identifiers.
Simple case
This will work with PostgreSQL 9.1 :
SELECT *, count(id) ct FROM my_table GROUP BY primary_key_column(s) ORDER BY ct DESC;
It requires primary key columns in the GROUP BY
. The results are identical for MySQL query, but ct
will always be 1 (or 0 if id IS NULL
) - it is useless to find duplicates.
Group other than primary key columns
If you want to group other columns, things get more complicated. This query mimics the behavior of your MySQL query - and you can use *
.
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;
This works because DISTINCT ON
(PostgreSQL-specific), such as DISTINCT
(SQL-Standard), is applied after the window function count(*) OVER (...)
. Window functions (with the OVER
clause) require PostgreSQL 8.4 or later and are not available in MySQL.
Works with any table, regardless of primary or unique constraints.
1
in DISTINCT ON
and ORDER BY
is simply abbreviated to refer to the sequence number of an item in a SELECT
list.
SQL Fiddle to demonstrate how side by side.
See more in this close answer:
count(*)
vs count(id)
If you're looking for duplicates, you're better off with count(*)
than count(id)
. There is a subtle difference if id
can be NULL
because NULL
values ββare not taken into account - while count(*)
counts all rows. If the id
is NOT NULL
, the results are the same, but count(*)
is usually more appropriate (and a little faster).