Ever heard of LATERAL joins/CROSS APPLY?
SELECT loop.value, x.squared
FROM generate_series(1,5) AS loop(value)
CROSS JOIN LATERAL (SELECT loop.value * loop.value AS squared) AS x;And this is the point I was trying to make.
Instead of start with the "how", learn to do the "what".
- Reference data from the previous part of the query (the "left-hand side")
- Return multiple columns
The only way you can achieve it is with LATERAL/CROSS APPLY.
Regular correlated subqueries can only return a single column, so something like this doesn't work:
SELECT
loop.val, (SELECT loop.val * loop.val, 'second column') AS squared
FROM
(SELECT loop.val FROM generate_series(1,5) AS loop(val)) as loop
You'd get: error: subquery must return only one columnIt's sets all the way down. A set of f(x) is still a set.
CREATE TEMP TABLE temp_results(value int, value_squared int);
DO $$
DECLARE
r int;
BEGIN
FOR r IN SELECT generate_series FROM generate_series(1,5)
LOOP
INSERT INTO temp_results VALUES (r, r * r);
END LOOP;
END$$;
SELECT * FROM temp_results;But you're right. Postgres does allow for-loops like this. (They're also slower than the equivalent set-oriented approach.)
https://chat.openai.com/share/931b1778-6393-4e86-94b4-b3b5a5...
SELECT loop.value, loop.value * loop.value
FROM generate_series(1,5) AS loop(value)The reason people use a relational database is because it has loops that are faster, safer, and more efficient than anything you can write.
The point is that by getting rid of loops you remove one way of telling the computer "How" to do it. Start here, do it in this order, combine the data this way.
When "How" is a solved problem, it is a waste of your brain to think about that again. "What" is a better use of your brain cycles.
different kind of loops can be different, e.g. 2 nested loop with quadratic time:
for i in t1: for j in t2:
vs sort + merge join with n log n time.
WITH RECURSIVE cnt(x) AS ( SELECT 1 UNION ALL SELECT x+1 FROM cnt LIMIT 5 ) SELECT x FROM cnt;
And then do a regular CROSS JOIN on that table.
It's not clear to me that (mathematically) a lateral join can be reduced to a recursive cte (and if the performance of a recursive cte would be acceptable for the cases where it does work as a substitute).
> Maybe it could be useful to ask questions that are similar to writing testcases "how can I verify that my query is doing the right thing"?
that seems like a good thread to pull on!
The number of use cases which are too heavy to finish in hours but small enough to fit in a single instance is pretty limited.
b) Only basic SQL works on any database and even then there are major differences in how they treat things like nulls, type coercion etc.
Programmers think the most valuable language is a programming language. Therefore, an LLM that can generate quality code in that language should also be extremely valuable.
I'd argue that the most valuable language is the natural language of the organization you're writing code for.
That language is vague and ambiguous, and encapsulates many hidden assumptions about how that organization works.
For example, if the organization is a retailer or a wholesaler, you might ask the LLM to generate SQL to return last month's sales and inventory for each site and product category.
The LLM can query the database system tables and guess which tables have sales transactions and inventory transactions. The LLM can look at foreign key definitions to make a good guess how to join these tables with metadata about items, sites, categories and the calendar.
But will the LLM know that inventory is a stock, and sales is a flow? Will it know it should sum the sales transactions but average the inventory balances, or take just the beginning or ending inventory balance?
Many human engineers struggle to translate ambiguous requests in natural language into code which reflects the assumptions and mechanics of the organization.
An LLM that generates consistently useful code needs a world model of how things work, not just how to write code.
Whilst Snowflake is pretty popular the days of elaborately modelled EDWs are long gone.
And so typically I find I am doing queries, transformations etc in some abstraction layer e.g. Spark on a data lake, ORM for web applications etc.
They're more prevalent than ever in my experience. Consider the popularity of dbt.
Don't forget the models other's create for you - often hilariously slow code to present a set of facets that often barely align with your business delivery needs; and don't forget to sync it even more slowly with Fivetran, the DE platform of the future!
This doesn't make any sense, or I'm guessing you've never actually used it. Modeling is something you can do with dbt, not what dbt does (or is, or can be?). I've used it to create data marts and EDW's with hundreds of tables, no differently than I would have created a decade ago with other tools.
The C for loop on the other hand…
SQL was created in 60s. It has not really kept up with the pace of modern programming language ergonomics. It was made for a single person executing a batch job query pulling data from the database.
On the other hand, I kind of agree SQL is good to learn. It's an counter example on how not to design a programming language.
The IBM System R and SEQUEL paper was 1974, while Oracle 2 was the first commercial database which added it in 1979.
Despite all the hate MongoDb deserves, it solved the problem how application developers can easily get data in and out of a database.
1. The order of the phrases, the lack of trailing commas, the fact that an awful organization controls the standards and gatekeeps them to a bizarre extent.
They may save you a bit of time initially but when your company gets bigger, the ORMs will become a bottleneck.
For example I've encountered queries that are not only slow, but they generate several hundred megabytes of output all of which is sent to the user's web browser where JavaScript selects the relevant two kilobytes of data to show the user.
The worst I've ever seen was a system where every single write to the database would be sent to every single web browser viewing certain webpages. 99.999999% of the writes were completely irrelevant and javascript in the browser would simply disregard them. The server load was immense... and eventually our Sysadmin brought it to someone's attention. Where we found out it was leaking sensitive data.
At which point - but not earlier! - you just make your ORM print the queries, fix them manually (or write them from scratch). You then can ditch the ORM, use it as a query builder DSL only, or use escape hatches provided by the ORM to inject raw SQL.
Don't use ORMs as a crutch to get away with not knowing SQL, that's bad. However, saving "a bit" - and with good ORMs, that "bit" is quite large - of time in the beginning is often very valuable. Just have a clear "exit strategy" for when (and in 90% of projects, if) it's needed.
Also the way each DB supports its own dialer is quite maddening.
I found while declarative and functional programming languages are not as often used, however learning them made me a better programer.
[1]: https://stackoverflow.com/questions/10925689/functional-prog...
2. Combining and slicing data is a craft, and doing it subtly wrong in one step can lead to fatal errors in the outcome.
And most importantly, it can be very difficult to notice. Numbers don't smell.
That is why I would be very hesitant to give a slightly more than trivial task to an engine that fails 25% of the time.
But I guess that is the same as any other programming task. Just that other programming tasks require a lot of boilerplate where an AI can help. SQL is much more straight to it.
Maybe it could be useful to ask questions that are similar to writing testcases "how can I verify that my query is doing the right thing"?