Fundamentally, SQL lacks meaningful abstraction, and there's no sane way to package very common operations.
Say you want to find elements in a row that correspond to some maximum value when grouped by date. Today, you'd need to write something like this EVERY SINGLE TIME:
``` SELECT sd1.sale_person_id, sd1.sale_person_name, sd1.no_products_sold, sd1.commission_percentage, sd1.sales_department FROM sales_department_details sd1 INNER JOIN (SELECT sale_person_id, MAX(no_products_sold) AS no_products_sold FROM sales_department_details GROUP BY sale_person_id) sd2 ON sd1.sale_person_id = sd2.sale_person_id AND sd1.no_products_sold = sd2.no_products_sold; ```
Wouldn't something like this be nicer?
``` SELECT sale_person_id, max(no_products_sold) as max_sold, link(sale_person_name, max_sold), FROM sales_department_details ```
Frankly, it seems like some sort of macro system is needed. Perhaps the SQL compiles into the above?
For me the value of being able to walk up to an unfamiliar database of widely varying tech and start getting value out of it immediately is the killer app. Macros or other DB-specific extensions would be useful at times, but I’m not sure how much they would enable solving the messiness problem in a generic way that reshapes the paradigm more broadly. My instinct is the messiness is a consequence of the direct utility and trying to make it nicer from a programmerly aesthetics point of view might be hard to sell. It’s not like SQL doesn’t have affordances for aesthetics already (eg. WITH clauses).
smh...
SQL views are useful for that kind of thing too.
SELECT * FROM
(SELECT DENSE_RANK() OVER ( PARTITION BY sd1.sale_person_id ORDER BY sd1.no_products_sold DESC) r ,sd1.sale_person_id ,sd1.sale_person_name ,sd1.no_products_sold ,sd1.commission_percentage ,sd1.sales_department
FROM sales_department_details sd1) sd
Where sd.r = 1
do the same without the inner join?
Views, materialized views, CTEs.
[1]: https://carlineng.com/?postid=sql-critique#blog [2]: https://carlineng.com/?postid=malloy-intro#blog
you can simply assign a subquery to a variable and reuse it.
PS: a lot of you are saying use views. thats dangerous. In most cases, thats a nice way to end up with ballooning autovacume processes as your databasse gets bigger. Materialized views are fine as long as your use case doesn't need realtime accuracy.
select sale_person_id, sale_person_name, no_products_sold, commission_percentage, sales_department from sales_department_details natural join max_products_sold;
Just asking for mooar build in stuff just leads to bloated software.
https://www.scattered-thoughts.net/writing/against-sql (found from HN a week or so ago)
Every expression represents a filter of some kind.
In SQL (and in relational algebra), every expression represents a dataset.
That means composing SQL expressions is composing data, not composing operations on data.
Since there is a somewhat low, backwards-compatible barrier to entry to build a combinator language on top of SQL (Pine is an example), whether or not trading the increased learning curve of using combinators for better composability is a good idea can stand the test of time.
[1]: https://github.com/pine-lang/pine [2]: https://stedolan.github.io/jq/
SELECT
sd1.sale_person_id,
sd1.sale_person_name,
sd1.no_products_sold,
sd1.commission_percentage,
sd1.sales_department
FROM
sales_department_details sd1
INNER JOIN (
SELECT
sale_person_id,
MAX(no_products_sold) AS no_products_sold
FROM sales_department_details
GROUP BY sale_person_id
) sd2
ON
sd1.sale_person_id = sd2.sale_person_id
AND sd1.no_products_sold = sd2.no_products_sold;
I think it is a remarkably well designed language. I often get decent results for minimal effort. It isn't something I use day to day but more often month to month and I generally forget what I learned a couple of years ago.
For example, I wanted to clear down some records for a defunct client from our backup results database. I started by using SELECT to reliably find the customer (not as simple as it might sound). Then I construct an INNER JOIN (in this case most joins are the same) to link to the jobs. A SELECT COUNT(*) experiment looks about right. I snapshot the VM and change my experiment to a DELETE.
SQL is a bit strange but it lends itself to experimentation ... to results, way better than any other language I know.
Then you get into functions and views and the like. SQL has just enough complication for whatever job you have at hand and no more.
I recently ran up a query in Icinga2 (Director) against a MariaDB and it seemed to write itself. I get far fewer syntax errors in SQL than anything else that I try to abuse!
root > people, # "root" keyword starts the document
person > person, # maps table context to a node
.age > @age, # @ maps a column to an attribute node
.first_name > name/first, # maps a column to a node
.last_name > .../last, # ... reuses the previous node's path
account.person_id +> person.person_id, # +> performs an INNER JOIN
account > account, # context is now "account" node
.id > @id, # account id attribute
^, # pop stack to previous table context
address > address, # switch context to "address" node
.*, # glob remaining columns
; # Denotes optional WHERE clause
The query produces:
Charles
Goldfarb
456
123 Query Lane
San Francisco
It wouldn't take much to make that a JSON document.
2) SQL statement syntax should start with the table specification so you can get autocompletion help when doing the columns and other expressions. The INSERT statement has it right, while SELECTs suck because the columns are specified before the WHERE clause, so there is no context. At least provide alternate syntaxes like SELECT FROM