Window Functions in SQL (2013)
blog.jooq.org
blog.jooq.org
This is why any decent columnar/timeseries db has its own often arrish query language to take advantages of ordering information inherent in the data. There is an order in that index and SQL table, you just don't have good tools to access and use it.
This touches on a conversation I was having a couple weeks ago where somebody was saying that column/array storage is purely a backend consideration and don't need to care about it in the front end of the database. That view gets you ugly primitives like LAG/LEAD. Being able to exploit your backend decision is paramount to performance.
Products like Informix or KDB+ just give you full access to the data on and off disk as an array so you ca build complex windowing primitives (and even store them and reuse them later).
(PS: I just find this really funny. KDB+ is probably is the only database I know that literally does streaming analytics on a Raspberry Pi. No joke, the full DB on Linux ARM/Pi. https://kx.com/download/ )
You have Hadoop/MR and Monet in the OSS group. SysbaseIQ, KDB, Teradata, Vertica, VectorWise, etc. all provide either extended SQL or additional query support to use ordering information in some (often weak) way.
You can even count Oracle In Memory Analytics with TSQL with its cursor model if you really want.
For example for KDB to get the last price and sum of volumer for each second of AAPL you would do in KSQL:
select last px, sum vol by time.second from trade where sym=`AAPL
on it can be done in its lower level language K/Q as (approx, I'm a little rusty) g:group trade.time.second @ where trade.sym=`AAPL
flip`px`vol!(last each trade.px g; sum each trade.vol g)There were a couple really, really cool tech talks I've been to. The title alone gives it props :)
"where Rumsfeldism & Kx collide"
https://kx.com/2014/12/07/visualizing-really-big-data/
in case you're curious about one of the other: a polymer hypergrid with an absurd amount of real time updating data:
http://openfin.github.io/fin-hypergrid-polymer-demo/componen...
Perhaps you're hinting at the idea that it's too easy to screw this up as a user, for it to be inefficient
The case it does work is that you are ordered on timestamp (for example), the query planner properly figures to use any filtering indexes and sequential indexes, ... magic occurs
Now the job is making an SQL statement that the query planner can actual understand and optimize since SQL lacks so much of the machinery for order-dependent processing (this was a feature when SQL was conceived remember).
(Note the involvement of IBM. Dunno whether this has made it into DB2, but a lot of really interesting research has; also keep in mind that whatever IBM wants to put in DB2 has a high probability of making it into the SQL standard).
Of course, SQL is by far more general purpose than producing ordered stuff. In fact, ordering is a completely non-relational thing that was even criticised in SQL in early days (such as offsets, limits, duplication, etc.). But SQL has learned to shoehorn foreign concepts into the language / platform for a long time, so I'm just curious about a concrete example where SQL window functions fail (and couldn't be fixed) in SQL for you.
(When the query returns tomorrow morning you realize that LAG was actually useless because your observation arrivals weren't periodic and you need to deal with / bucket for that to actually get usable results).
We used to run a lot of LEAD/LAG queries on a very, very large Oracle install could never get the performance we wanted out of it. Basically turned it into a very expensive file server that spat out HDF that we then processed by a mix of shell and python. Should not have been faster than the overpriced heater in the corner we called a database but was.
sum(price * quantity) over w / sum(quantity) over w as VWAP
⋮
window w as (partition by stock order by time range 30000 preceding)
Totally willing to believe first-hand experience, but surprised and disappointed if it's impossible to make that fast. (Apologies if I'm totally misunderstanding the use case).There are probably also difference between OVER when used in TSQL and PLSQL.
Last time I had to do this was actually with real-time advertising bidding, and it was across keywords, not ticker symbols (many more, much sparser). We had a 20 millisecond budget, and had to break the queries up to at least get partial results to push out bid even if we didn't have all the results back in from the database that we wanted.
We used OVER+RANGE for average price, but needed LAG for first derivative (is the price trending up or down). We had to start doing roll ups of the data hourly and be constantly trimming to keep the real-time performance high enough, but that meant we needed to have have a separate off-line analytical system. Common to do, but still I think it can be done without it if you use the correct tech stack.
How about Oracle 12c's MATCH_RECOGNIZE, though?
http://www.oracle.com/ocom/groups/public/@otn/documents/webc...
It didn't give any examples of queries going both directions, e.g. the down-up V first example. You probably often also want the up-down ^ shapes too. It would be nice if the PATTERN had alternation too "STRT (DOWN+ UP+)|(UP+ DOWN+)" so you didn't need to double your queries. Or else you're probably better off creating a temp on CUR-LAG(1) to give you the sign and then pattern match the sign (if that makes sense).
Oracle really does go out of their way to keep SQL modern though. I remember the first time I saw a "CONNECT BY". lol. I had an interview a few months later and was asked to write an SQL query to basically traverse a tree (the gist of it). I being a young smart ass gave the correct answer (you can't) and proceeded to write the START / CONNECT just to show off a little.
Hah, yeah CONNECT BY is great for simple recursion, but for more complex (probably less performing) cases, I prefer the standard approach with CTEs...
When the "Why's that company so big? I can do that in a weekend." article came out last week:
https://news.ycombinator.com/item?id=12626314
I immediately thought of Kx and KDB and how it is literally the exact opposite. If people only knew how small the firm started with Arthur hacking away seemingly out developing entire corporations they would laugh.
"Yeah give me about two years and a dev team of a about 20 then about 10 for QA and we've have something shippable... abother year or two for performance... 5 years we'll be in the hunt." Yeah, we'll this guy over here basically did it in six months with only two others. And it's 100x faster than anything else. Why can't you do that?
Given his history too with A+ at Morgan Stanley, it wouldn't be the first time a team of a small handful he was at the core of beat the socks off everybody else either. Some people just have this amazing ability to see simplicity. I've had the pleasure of being around a few people boss like that.
Agreed.
A few years of writing expressive, powerful, performant SQL in big blocks will really change your mental model of data across _all_ languages.
I highly recommend a deep dive into the relational world, and I feel super grateful for the SQL-focused job I held previously. Brought those lessons back with me to both FP and OO.
It would also be great if windows could be function parameters in Postgres. I like to abstract complicated conditionals and calculations into functions, but it falls down if you're operating over a window.
min(ST_Distance(this.point, foo.point)) over (blah)
That is, for each 'foo', get me the minimum distance to another foo in the current window.The second peeve is to do with filters, e.g.:
count(*) filter (where this.time - foo.time < 5 and type_id = 42) over (blah)
That is, how many events of type 42 are there up to 5 seconds before the current event.In both cases, it's sad not being able to address the current row as well as the row in the window. I'm not saying either form is completely impossible to get working somehow, I just think it'd be a nice feature.
Do note that Oracle has the KEEP clause that might probably solve your issue with aggregate functions only... But it's a rather esoteric, vendor-specific extension.
Anyway, I do agree, what you're describing would be a very nice feature.
https://dveeden.github.io/modern-sql-in-mysql/
(aka "Look, window functions are coming")
How is that similar? plv8 is a procedural language (javascript) for writing user defined functions.