Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL ORDER BY within OVER clause incompatible with CLR aggregation?

Tags:

c#

sql

sqlclr

Preamble I have been investigating a concept and what I am posting below is a cut down version of what I have been trying. If you look at it and think "That doesn't make any sense to do it that way" then it is probably because I doesn't make any sense - there may be more efficient ways of doing this. I just wanted to try this out because it looks interesting.

What I am attempting to do it to calculate arbitrary calculations using CLR custom aggregations in SQL using a Reverse-Polish-like implementation. I'm using the data:

K | Amt | Instruction | Order
--+-----+-------------+------
A | 100 |        Push |     1
A |   1 |    Multiply |     2
A |  10 |        Push |     3
A |   2 |    Multiply |     4
A |     |         Add |     5
A |   1 |        Push |     6
A |   3 |    Multiply |     7
A |     |         Add |     8

The result of the calculation should be 123 ( = (100 * 1) + (10 * 2) + (1 * 3) ).

Using the following SQL (and the CLR functions ReversePolishAggregate and ToReversePolishArguments* that I have written) I can get the correct result:

SELECT K
  , dbo.ReversePolishAggregate(dbo.ToReversePolishArguments(Instruction, Amt))
FROM dbo.ReversePolishCalculation
GROUP BY K;

The Problem I want to generalise the solution more by putting the instructions and order in a separate table so that I can create calculations on arbitrary data. For example, I was thinking of a table like this:

Item |     Type | Amount
-----+----------+-------
   A | Budgeted |     10
   A |   Actual |     12
   B |   Actual |     20
   B | Budgeted |     18

and joining it to a calculation table like this

    Type | Instruction | Order
---------+-------------+------
Budgeted |        Push |     1
  Actual |       Minus |     2

to calculated whether each item is over or under budget. The important consideration is that minus is non-commutative so I need to specify the order to ensure that the actual amount is subtracted from the budgeted amount, not the other way around. I expected that I would be able to do this with the ORDER BY clause inside the OVER clause of the aggregation (and then a little more tweaking that result).

SELECT K
  , dbo.[ReversePolishAggregate](
    dbo.[ToReversePolishArguments](Instruction, Amt)) 
    OVER (PARTITION BY K ORDER by [Order])
FROM dbo.ReversePolishCalculation;

However I get the error:

Incorrect syntax near the keyword 'ORDER'.

I have checked the syntax by running the following SQL statement

SELECT K
  , SUM(Amt) OVER (PARTITION BY K ORDER BY [Order])
FROM dbo.ReversePolishCalculation;

This works fine (it parses and runs, although I'm not sure that the result is meaningful), so I am left assuming that this is a problem with custom CLR aggregations or functions.

My Questions Is this supposed to work? Is there any documentation saying explicitly that this is not supported? Have I got the syntax right?

I'm using Visual Studio 2012 Premium, SQL Server Management Studio 2012 and .NET framework 4.0.

* I created 2 CLR functions as a work-around to not being able to pass multiple arguments into a single aggregation function - see this article.

EDIT: This post looks like it is not supported, but I was hoping for something a little more official.

like image 797
Jonny Avatar asked Jun 11 '14 14:06

Jonny


1 Answers

As an answer:

Officially from Microsoft, No.

http://connect.microsoft.com/SQLServer/feedback/details/611026/add-support-for-over-order-by-for-clr-aggregate-functions

It doesn't appear to have made it into 2014 (or 2016 CTP 3) ... no mentions of many transact-sql changes:

http://msdn.microsoft.com/en-us/library/bb510411.aspx#TSQL

like image 137
N West Avatar answered Oct 06 '22 00:10

N West