29

I would like to have a Sql Server equivalent of the PostgreSQL distinct on ()

a  b
----
1  1
1  2
2  2
2  1
3  3

select distinct on (a) * 
from my_table

a  b
----
1  1
2  2
3  3

I could do in SQL Server:

select a, min(b) -- or max it does not matter
from my_table
group by a

But in cases where there are many columns and the query is an ad hoc one it is very tedious to do. Is there an easy way to do it?

bobs
  • 21,844
  • 12
  • 67
  • 78
Clodoaldo Neto
  • 118,695
  • 26
  • 233
  • 260
  • Possible duplicate of [Select first row in each GROUP BY group?](https://stackoverflow.com/questions/3800551/select-first-row-in-each-group-by-group) – Michael Freidgeim Sep 28 '19 at 14:45
  • @MichaelFreidgeim that answer only demonstrates that CTE is semantic replacement for `DISTINCT ON` but CTE stands far behind from Postgres extension in land of performance. – gavenkoa May 03 '23 at 21:21

2 Answers2

24

You can try ROW_NUMBER, but it can affect your performance.

;WITH CTE AS
(
    SELECT *, ROW_NUMBER() OVER(PARTITION BY a ORDER BY b) Corr
    FROM my_table
)
SELECT *
FROM CTE
WHERE Corr = 1
Lamak
  • 69,480
  • 12
  • 108
  • 116
22

In addition to the accepted answer, you can avoid using two sentences and use a sub select like this

SELECT part.*
FROM (  SELECT *, ROW_NUMBER() OVER(PARTITION BY a ORDER BY b) Corr
    FROM my_table) part
WHERE part.Corr = 1