Can you use GROUP BY and Window function together? - nosql

This is the code I'm trying to use
From orders as o, o.items as it
Group by o.orderno
Select o.orderno, Max(it.price) OVER (PARTITION BY it.itemno ORDER BY o.orderno) as MaxPrice;
But SQL++ returns an error which states:
Cannot resolve alias reference for undefined identifier it (in line 3, at column 23)
I'm trying to figure out if both GROUP BY and a window function can be used in the same query.

WINDOW functions and GROUP/Aggregates can be used together.
But WINDOW functions must depended on (including OVER clause expressions) constant, group expressions or aggregate functions.
No other expression is allowed. This is restriction of GROUP (The reason once you do group by, There is no way you can reduce other expression to single value with out aggregate). Example for GROUP BY restriction

Related

Why can you nest aggregate functions when using a window function in PostgreSQL?

I'm trying to understand window functions a bit better, and I'm stumped as to why I can't run a nested aggregate function normally, but I can when using a window function.
This is the dbfiddle I'm working off of: https://dbfiddle.uk/?rdbms=postgres_11&fiddle=76d62fcf4066053db18783e70269438c
Before running the window function, basically everything else in my query is evaluated (JOIN and GROUP BY).
So I believe the data the window function is working off of is something like this (after grouping):
Or is it something like this?
So why can I do this: SUM(COUNT(votes.option_id)) OVER(), but I can't do it without OVER()?
As far as I understand, OVER() makes the SUM(COUNT(votes.option_id)) run on this related data set, but it's still a nested aggregate function.
What am I missing?
Thank you very much!
If you have something like SUM(COUNT(votes.option_id)) OVER() you can think of COUNT(votes.option_id) as a column generated in the GROUP BY clause.
According to the documentation:
The rows considered by a window function are those of the “virtual table” produced by the query's FROM clause as filtered by its WHERE, GROUP BY, and HAVING clauses if any.
This means that window functions operate at a level above the GROUP BY clause and any aggregates, and therefore aggregates are available to be used inside window functions. In your example the "virtual table" corresponds to the second picture.
The reason you cannot nest aggregate functions is that you cannot have multiple levels of GROUP BY on the same query. Similarly you cannot nest window functions. The documentation is clear on what type of expression are allowed inside aggregate and window functions. For aggregates functions we can use:
any value expression that does not itself contain an aggregate expression or a window function call
while for window functions we can use:
any value expression that does not itself contain window function calls

SSRS multi value parameter - can't get it to work

First off this is my first attempt at a multi select. I've done a lot of searching but I can't find the answer that works for me.
I have a postgresql query which has bg.revision_key in (_revision_key) which holds the parameter. A side note, we've named all our parameters in the queries with the underscore and they all work, they are single select in SSRS.
In my SSRS report I have a parameter called Revision Key Segment which is the multi select parameter. I've ticked Allow multi value and in Available Values I have value field pointing to revision_key in the dataset.
In my dataset parameter options I have Parameter Value [#revision_key]
In my shared dataset I also have my parameter set to Allow multi value.
For some reason I can't seem to get the multi select to work so I must be missing something somewhere but I've ran out of ideas.
Unlike with SQL Server, when you connect to a database using an ODBC connection, the parameter support is different. You cannot use named parameters and instead have to use the ? syntax.
In order to accommodate multiple values you can concatenate them into a single string and use a like statement to search them. However, this is inefficient. Another approach is to use a function to split the values into an in-line table.
In PostgreSQL you can use an expression like this:
inner join (select CAST(regexp_split_to_table(?, ',') AS int) as filter) as my on my.filter = key_column
Then in the dataset properties, under the parameters tab, use an expression like this to concatenate the values:
=Join(Parameters!Keys.Value, ",")
In other words, the report is concatenating the values into a comma-separated list. The database is splitting them into a table of integers then inner joining on the values.

TSQL / SSRS : Using LIKE with multi-valued parameters

I am trying to determine a solution to filter records using LIKE with a multi-valued parameter. In a simplistic example a user wants to return a set of 5-digit Object codes by entering the following in a parameter window in a SSRS report:
#parm_Object
1,24,333,34567
This ideally would return Object codes satisfying the following criteria:
1 : All Object codes starting with '1'
24: All Object codes starting with '24'
333: Similar
34567: Object code '34567'
I guess a starting point for me would be to determine whether this could be handled in the actual query, or should I do it on the SSRS side.
general good practice is to get rid of the data you don't need ASAP. so that would be in the query.
a SSRS multivalued parameter will show up as a comma separated list in the query.
the first step is to get from this comma separated list to a table (or table function), then you can join this table and apply like operators
for example
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS a
INNER JOIN dbo.split1('test,fafa,tata') b
ON 1=1
WHERE a.COLUMN_NAME like b.Value + '%'
will return rows having column names starting with test, fafa or tata. the dbo.split1 function you have to write your own or get one from the internet. the link suggested by Tab Alleman for example.

JPQL Group By not working

This is my simple JPQL:
SELECT s
FROM Site s
GROUP BY s.siteType
siteResult = q.getResultList();
for (Site site : siteResult) {
// loops all sites
}
This query returns all sites, including sites of the same siteType.
I'm using JPA 2.0 Eclipselink.
Whats wrong here?
Such a query does not make sense. If you use GROUP BY, other attributes in SELECT should be aggregated. As it is said in JPA specification:
The requirements for the SELECT clause when GROUP BY is used follow
those of SQL: namely, any item that appears in the SELECT clause
(other than as an aggregate function or as an argument to an aggregate
function) must also appear in the GROUP BY clause. In forming the
groups, null values are treated as the same for grouping purposes.
If you think SQL counterpart of your query:
SELECT s.attr1, attr2, s.siteType
FROM site s
GROUP BY (s.siteType)
you notice that it is hard to imagine which possible value of attr1 and attr2 should be chosen.
In such a case EclipseLink with derby just drops GROUP BY away from the query, which is of course little bit questionable way to handle invalid JPQL. I like more how Hibernate+MySQL behaves with such a invalid JPQL, it fails with quite clear error message:
java.sql.SQLSyntaxErrorException: The SELECT list of a grouped query
contains at least one invalid expression. If a SELECT list has a GROUP
BY, the list may only contain valid grouping expressions and valid
aggregate expressions.
Answer to comment:
One Site contains probably also attributes other than siteType as well. Lets use following example:
public class Site {
int id;
String siteType;
}
and two instances: (id=1, siteType="same"), (id=2, siteType="same"). Now when type of select is Site itself (or all attributes of it) and you make group by by siteType, it is impossible to define should result have one with id value 1 or 2. Thats why you have to use some aggregate function (like AVG, which gives you average of attribute values) for remaining attributes (id in our case).
Behind this link: ObjectDB GROUP BY you can find some examples with GROUP BY and aggregates.

sqlalchemy group_by error

The following works
s = select([tsr.c.kod]).where(tsr.c.rr=='10').group_by(tsr.c.kod)
and this does not:
s = select([tsr.c.kod, tsr.c.rr, any fields]).where(tsr.c.rr=='10').group_by(tsr.c.kod)
Why?
thx.
It doesn't work because the query isn't valid like that.
Every column needs to be in the group_by or needs an aggregate (i.e. max(), min(), whatever) according to the SQL standard. Most databases have always complied to this but there are a few exceptions.
MySQL has always been the odd one in this regard, within MySQL this behaviour depends on the ONLY_FULL_GROUP_BY setting: https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html
I would personally recommend setting the sql_mode setting to ANSI. That way you're largely compliant to the SQL standard which will help you in the future if you ever need to use (or migrate) to a standards compliant database such as PostgreSQL.
What you are trying to do is somehow valid in mysql, but invalid in standard sql, postgresql and common sense. When you group rows by 'kod', each row in a group has the same 'kod' value, but different values for 'rr' for example. With aggregate functions you can get some aspect of the values in this column for each group, for example
select kod, max(rr) from table group by kod
will give you list of 'kod's and the max of 'rr's in each group (by kod).
That being sad, in the select clause you can only put columns from the group by clause and/or aggregate functions from other columns. You can put whatever you like in where - this is used for filtering. You can also put additional 'having' clause after group that contains aggregate function expression that can also be used as post-group filtering.