Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add boolean aggregate functions EVERY, ANY and SOME [CORE5975] #6227

Open
firebird-automations opened this issue Dec 23, 2018 · 5 comments
Open

Comments

@firebird-automations
Copy link
Collaborator

Submitted by: @mrotteveel

Votes: 1

The SQL standard defines the boolean aggregate functions EVERY, ANY and SOME (see SQL:2016-2 10.9 <aggregate function>). In a way, these are the counterpart of the quantified comparison predicates (ALL, ANY and SOME) that Firebird already supports.

The value expression inside the aggregate is a boolean expression, eg

EVERY(somebooleancolumn) is true if all values for somebooleancolumn are true (also true if the group set is empty, which can be relevant when also using a FILTER-clause).
ANY(x = 'y' and someothercolumn is null) is true if at least one row in the group set has a column x with value 'y' and someothercolumn null.

From the standard:

"""
Syntax Rules
[..]
7) If <general set function> is specified, then:
[..]
b) Let DT be the declared type of the <value expression>.
[..]
e) If EVERY, ANY, or SOME is specified, then DT shall be boolean and the declared type of the result is boolean.

[..]
General Rules
[..]
7) If <general set function> is specified, then:
a) Let TX be the single-column table that is the result of applying the <value expression> to each row of T1 and eliminating null values. If one or more null values are eliminated, then a completion condition is raised: warning — null value eliminated in set function.
b) Case:
i) If DISTINCT is specified, then let TXA be the result of eliminating redundant duplicate values from TX, using the comparison rules specified in Subclause 8.2, "<comparison predicate>", to identify the redundant duplicate values.
ii) Otherwise, let TXA be TX.
[..]
d) Case:
[..]
vi) If EVERY is specified, then
Case:
1) If the value of some element of TXA is False, then the result is False.
2) Otherwise, the result is True.
vii) If ANY or SOME is specified, then
Case:
1) If the value of some element of TXA is True, then the result is True.
2) Otherwise, the result is False.
"""

@firebird-automations
Copy link
Collaborator Author

Commented by: @livius2

I see that this is only shortcut to existing aggregates to avoid unnecessary CASE WHEN ..?
Or is here some case which cannot be done already?

@firebird-automations
Copy link
Collaborator Author

Commented by: @mrotteveel

@Karol by that reasoning you don't need most of the aggregate functions. In any case it sounds more like you're thinking of the FILTER-clause, which has already been added as part of CORE5768.

Adding these aggregate functions makes for more readable expressions, or at least, I think attempting to express EVERY using existing aggregate functions will lead to extremely unclear and unreadable expressions.

@firebird-automations
Copy link
Collaborator Author

Commented by: @livius2

No, Mark. I really ask if something cannot be done with CASE WHEN i am simply interested in new things.
I like this sortcuts very much, they simplify things and are usefull, same as FILTER clause.

@firebird-automations
Copy link
Collaborator Author

Commented by: @mrotteveel

@Karol, sorry I misread that :)

For example (using employee database)

select any(emp_no < 4) from employee

is equivalent to

select count(case when emp_no < 4 then 1 end) > 0 from employee

or (using filter clause):

select count(*) filter (where emp_no < 4) > 0 from employee

And

select every(emp_no > 1) from employee

would be

select count(*) = count(case when emp_no > 2 then 1 end) from employee

or (using filter clause):

select count(*) = count(*) filter (where emp_no > 2) from employee

Things get more hairy when filter clauses are used though:

select every(emp_no > 12) filter (where job_code = 'Admin') from employee

is equivalent to something like

select count(*) filter (where job_code = 'Admin') = count(*) filter (where emp_no > 11 and job_code = 'Admin') from employee

Note that PostgreSQL has two aliases BOOL_AND for EVERY and BOOL_OR for ANY/SOME

@firebird-automations
Copy link
Collaborator Author

Commented by: @mrotteveel

The PostgreSQL documentation (https://www.postgresql.org/docs/11/functions-aggregate.html) also remarks on a potential parser ambiguity for ANY/SOME with the quantified comparison predicates:

"""
Boolean aggregates bool_and and bool_or correspond to standard SQL aggregates every and any or some. As for any and some, it seems that there is an ambiguity built into the standard syntax:

SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;

Here ANY can be considered either as introducing a subquery, or as being an aggregate function, if the subquery returns one row with a Boolean value. Thus the standard name cannot be given to these aggregates.
"""

This may be relevant for us as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant