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).