TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Modern SQL: With – Organize Complex Queries

165 pointsby MarkusWinandover 9 years ago

14 comments

olavggover 9 years ago
Markus Winand is a great SQL expert. I&#x27;m really grateful for everything that he shares with us. He writes well, explains us the differences between the different SQL engines. And his books are fantastic references.<p>I highly recommend his &quot;No to offset&quot; tutorial <a href="http:&#x2F;&#x2F;use-the-index-luke.com&#x2F;no-offset" rel="nofollow">http:&#x2F;&#x2F;use-the-index-luke.com&#x2F;no-offset</a> Should be common knowledge, but I still see offset being used way to often, even in core ORM frameworks :-(
评论 #10621800 未加载
colandermanover 9 years ago
If your query is complex enough to warrant a (non-recursive) CTE, it&#x27;s probably complex enough to warrant breaking that CTE out into a separate view (or function, if it performs a write). Now you can independently test and reuse that view, which you can&#x27;t do with a CTE.<p>(Bonus if you&#x27;re in Postgres: Postgres optimizes across views, but not across CTEs. Go figure.)
评论 #10621350 未加载
评论 #10621661 未加载
评论 #10621008 未加载
评论 #10621035 未加载
评论 #10621632 未加载
ycom13__over 9 years ago
Updatable CTEs are great, for example if you want to set a column to 1 where the date is the latest day for each value in a different column, you would do something like this<p><pre><code> ;WITH cte AS(SELECT ROW_NUMBER() OVER(PARTITION BY SomeVal ORDER BY SomeDate DESC) AS row, * FROM SomeTable) UPDATE cte SET id = CASE WHEN row = 1 THEN 1 ELSE 0 END </code></pre> Here is the DDL and DML in case you want to play around with this<p><pre><code> CREATE TABLE SomeTable(id int,SomeVal char(1),SomeDate date) INSERT SomeTable SELECT null,&#x27;A&#x27;,&#x27;20110101&#x27; UNION ALL SELECT null,&#x27;A&#x27;,&#x27;20100101&#x27; UNION ALL SELECT null,&#x27;A&#x27;,&#x27;20090101&#x27; UNION ALL SELECT null,&#x27;B&#x27;,&#x27;20110101&#x27; UNION ALL SELECT null,&#x27;B&#x27;,&#x27;20100101&#x27; UNION ALL SELECT null,&#x27;C&#x27;,&#x27;20110101&#x27; UNION ALL SELECT null,&#x27;C&#x27;,&#x27;20100101&#x27; UNION ALL SELECT null,&#x27;C&#x27;,&#x27;20090101&#x27;</code></pre>
评论 #10621180 未加载
Nimeoover 9 years ago
Wow, what I liked on this website is that you can turn off social plugins, why not more websites do that...
评论 #10620368 未加载
pmontraover 9 years ago
The optimization fence in PostgreSQL is usually bad for SELECTs but it has it&#x27;s own benefits. See this thread <a href="http:&#x2F;&#x2F;www.postgresql.org&#x2F;message-id&#x2F;201209191305.44674.db@kavod.com" rel="nofollow">http:&#x2F;&#x2F;www.postgresql.org&#x2F;message-id&#x2F;201209191305.44674.db@k...</a>
theallanover 9 years ago
What I really want from SQL is the ability to do a single select with one or more parts of each returned record being an array (defined by a one-to-many join) and others simple scalars.<p>It looks like Postgres can do it [1] with its JSON capabilities, and to be honest its being a little while since I&#x27;ve dug into it, so things might have changed (I&#x27;m actually not even sure I&#x27;m phrasing the question correctly), but the old way of doing a single select and then looping over it in whatever code is calling the SQL and doing N more selects, one for each row to get the sub-array is horrible.<p>[1] <a href="http:&#x2F;&#x2F;bender.io&#x2F;2013&#x2F;09&#x2F;22&#x2F;returning-hierarchical-data-in-a-single-sql-query&#x2F;" rel="nofollow">http:&#x2F;&#x2F;bender.io&#x2F;2013&#x2F;09&#x2F;22&#x2F;returning-hierarchical-data-in-a...</a>
评论 #10620747 未加载
评论 #10620808 未加载
评论 #10620340 未加载
评论 #10620417 未加载
评论 #10620319 未加载
评论 #10620803 未加载
reacwebover 9 years ago
Very interesting site, but does anyone know why Oracle and mysql have a so poor support of the standard ? It looks as if postgres was the only one trying to comply.
评论 #10620920 未加载
评论 #10620558 未加载
评论 #10620497 未加载
评论 #10620748 未加载
评论 #10620530 未加载
anc84over 9 years ago
with has completely changed my usage of PostgreSQL. I am a newbie and being able to split queries into logical small steps with this has made SQL much more fun.
评论 #10621276 未加载
mhdover 9 years ago
Sometimes SQL looks like a good spot to break out the old CWEB literate programming tools...
评论 #10623518 未加载
pjungwirover 9 years ago
A common pattern I still haven&#x27;t solved is this: I have table <i>A</i>, and now I want to add table <i>B</i> and give it one row for each row in table <i>A</i>. Then I want to add a foreign key column to table <i>A</i> pointing at the row I just added.<p>Of course this is easy to do with a loop, but can you do it all in pure SQL? If you have a solution I would love to see it.<p>Here is my history of attempts:<p><pre><code> DROP TABLE IF EXISTS dogs; DROP TABLE IF EXISTS doghouses; DROP SEQUENCE IF EXISTS dogs_id_seq; DROP SEQUENCE IF EXISTS doghouses_id_seq; BEGIN; CREATE SEQUENCE dogs_id_seq; CREATE SEQUENCE doghouses_id_seq; CREATE TABLE dogs ( id INTEGER PRIMARY KEY DEFAULT nextval(&#x27;dogs_id_seq&#x27;), name TEXT NOT NULL ); INSERT INTO dogs (name) VALUES (&#x27;Sparky&#x27;), (&#x27;Spot&#x27;) ; -- Now we want to give each dog a doghouse: CREATE TABLE doghouses ( id INTEGER PRIMARY KEY DEFAULT nextval(&#x27;doghouses_id_seq&#x27;), name TEXT NOT NULL ); ALTER TABLE dogs ADD COLUMN doghouse_id INTEGER REFERENCES doghouses (id); &#x2F;* -- ERROR: syntax error at or near &quot;INTO&quot; UPDATE dogs AS d SET doghouse_id = ( INSERT INTO doghouses (name) VALUES (d.name) RETURNING id ) ; *&#x2F; &#x2F;* -- ERROR: WITH clause containing a data-modifying statement must be at the top level UPDATE dogs AS d SET doghouse_id = ( WITH x AS ( INSERT INTO doghouses (name) VALUES (d.name) RETURNING id ) SELECT * FROM x ) ; *&#x2F; &#x2F;* -- ERROR: missing FROM-clause entry for table &quot;dogs&quot; WITH homes AS ( INSERT INTO doghouses (name) SELECT name FROM dogs RETURNING doghouses.id AS doghouse_id, dogs.id AS dog_id ) UPDATE dogs SET doghouse_id = homes.doghouse_id FROM homes WHERE dogs.id = homes.dog_id ; *&#x2F; -- ERROR: syntax error at or near &quot;INTO&quot; UPDATE dogs AS d1 SET doghouse_id = h.id FROM dogs d2 INNER JOIN LATERAL ( INSERT INTO doghouses (name) VALUES (d2.name) RETURNING id ) ON true WHERE d1.id = d2.id ; COMMIT;</code></pre>
评论 #10623887 未加载
评论 #10623643 未加载
评论 #10623322 未加载
评论 #10623375 未加载
dansoover 9 years ago
Wow, never knew this. I&#x27;ve been fine with just doing nested subqueries but this is definitely easier to read. Great to learn a helpful piece of everyday syntax before I&#x27;ve had my coffee.
iblaineover 9 years ago
Typically I advise people to use CTE&#x27;s for ad hoc queries and to avoid CTE&#x27;s for production code. CTE&#x27;s are easily abused.
评论 #10622311 未加载
jeltzover 9 years ago
One of the most useful things about CTEs is PostgreSQL&#x27;s support of having DELETE ... RETURNING and UPDATE ... RETURNING in the the WITH clauses. This way you can easily implement moving rows from one table to another.
ricketteover 9 years ago
Nice reference.