SQL ConstantCareuses PostgreSQL as a back end specifically, AWS RDS Aurora so I’ve spent a lot of time writing Postgres queries lately. Here are some of the things I’ve noticed that are different.
CTEs are optimization fences.In SQL Server, if you write this query:
With AllPosts AS (SELECT * FROM StackOverflow.dbo.Posts) SELECT * FROM AllPosts WHERE Id = 1;SQL Server builds a query plan for the entire operation at once, and passes the WHERE clause filter into the CTE. Theresulting query plan is efficient, doing just a single clustered index seek.
In Postgres, CTEs are processed separately first , and subsequent WHERE clauses aren’t applied until later. That means the above query works just fine but performs horribly. You’ll get much better results if you include your filters inside each CTE, like this:
With AllPosts AS (SELECT * FROM StackOverflow.dbo.Posts WHERE Id = 1) SELECT * FROM AllPosts;That’s less than ideal.
You can’t just leap into an IF statement.In SQL Server, you can just start typing conditional logic and execute it:
IF EXISTS (SELECT * FROM StackOverflow.dbo.Users) SELECT 'Yay' ELSE SELECT 'Nay';That’s useful if you want to do conditional processing, set variables up, populate them for different scenarios, etc.
In Postgres, you have to do a little setup to declare that you’re doing procedural code:
DO $$ BEGIN IF EXISTS (SELECT * FROM rule) THEN SELECT 'Yay'; ELSE SELECT 'Nay'; END IF; END $$;But that doesn’t work either, because you can’t output data from a DO:
ERROR:query has no destination for result data HINT:If you want to discard the results of a SELECT, use PERFORM instead. CONTEXT:PL/pgSQL function inline_code_block line 4 at SQL statement<sigh> You really want to create a function. Which reminds me: Postgres functions are the equivalent of SQL Server stored procedures. Sure, SQL Server’s user-definedfunctions have a really bad reputation: most of ’em get bad row estimates, inhibit parallelism, and cause performance tuners to point and giggle. Postgres functions? Totally different. Just basically stored procs.
And one less-important difference: GREATEST and LEAST.Every now and then, I need to find the higher (or lesser) of two things in a row. Let’s say our dbo.Users table has two columns, UpvoteDate and DownvoteDate, and I’m trying to find the most recent date that they cast ANY kind of vote. Postgres has this really cool trick:
SELECT GREATEST(LastUpvoteDate, LastDownvoteDate) AS VoteDate FROM dbo.Users;GREATEST is like MAX, but across columns. GREATEST and LEAST are two conditional expressions that we don’t get in SQL Server . Nifty.