Skip to content

SQL: Implement IIF(<cond>, <result1>, <result2>) #41420

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

Merged
merged 7 commits into from
Apr 23, 2019
Merged

Conversation

matriv
Copy link
Contributor

@matriv matriv commented Apr 22, 2019

Implement a more trivial case of the CASE expression which is
expressed as a traditional function with 2 or 3 arguments. e.g.:

IIF(a = 1, 'one', 'many')
IIF(a > 0, 'positive')

Closes: #40917

@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-search

Implement a more trivial case of the `CASE` expression which is
expressed as a traditional function with 2 or 3 arguments. e.g.:
```
IF(a = 1, 'one', 'many')
```

```
IF(a > 0, 'positive)
```

Closes: elastic#40917
Copy link
Member

@costin costin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
The only comment is whether this should be only IIF instead of IF since:
Oracle and SQL Server has a different syntax for IF (IF THEN)
SQL Server does support IIF in this form
Postgres does not support IF

Essentially only MySQL has this flavor of IF and frankly I would go after the IF THEN format in SQLServer/Oracle instead and drop this one since there would be too many choices IMO.


public class If extends Case {

public If(Source source, Expression condition, Expression result, Expression defaultValue) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defaultValue should be really else across the whole hierarchy. (if then else - vs if then default).

ifGroupByAndHaving
schema::count:l|gender:s|languages:byte
SELECT count(*) AS count, gender, languages FROM test_emp
GROUP BY 2, 3 HAVING IF(count(*) > 10, 'many', 'a few') = 'many'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@matriv
Copy link
Contributor Author

matriv commented Apr 23, 2019

IF indeed is only a MySQL flavour, but Imho doesn't hurt to have it together with IIF. The IF... THEN... ELSE... END IF statement comes from Oracle PL/SQL (declare functions/procedures, etc.) and not in the standard query language. Also for SQL server: https://docs.microsoft.com/en-us/sql/t-sql/language-elements/else-if-else-transact-sql?view=sql-server-2017 it's for control flow inside code blocks with loops, declared methods and variables, etc.

@astefan what do you think?

Copy link
Contributor

@astefan astefan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I left few small comments.

Regarding IIF vs. IF debate, I would keep IIF only. On one hand we have a bunch of aliases for all the date parts functions - ie "DAY_OF_MONTH", "DAYOFMONTH", "DAY", "DOM" where DAYOFMONTH is the "true" function name and others being just aliases we added for ease of use. But all these aliases do have the same functional behavior are cannot be confused with something else, whereas IF could potentially have a different meaning based on other SQL providers. And if we keep IF, some users might want to use it as they know it's used in Oracle PL/SQL.


[TIP]
=================
If functions can be combined to implement more complex logic simulating the <<sql-functions-conditional-case>>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capital letters IF.

@@ -2095,6 +2097,51 @@ elastic
;


Copy link
Contributor

@astefan astefan Apr 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to see, based on a previous issue fixed in the past, a query where you use a CONVERT without the optional parameter for IIF, with an alias and grouped by alias: SELECT CONVERT(IIF(languages > 1, IIF(languages = 3, '3')), SQL_BIGINT) AS cond FROM test_emp GROUP BY cond ORDER BY cond DESC.


private List<Expression> mutateChildren(If iif) {
List<Expression> expressions = new ArrayList<>(3);
expressions.add(new Equals(randomSource(), randomStringLiteral(), randomStringLiteral()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Equals here shouldn't have either first string different from the original one, either the second one, either both? I know there are small chances for this to happen in tests, but it can happen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be but the chances are really small and on top we are changing for sure the thenResult and the elseResult. But anyway for 100% correctness I'm changing it to create also a different Equals condition.

@matriv matriv changed the title SQL: Implement IF(<cond>, <result1>, <result2>) SQL: Implement IIF(<cond>, <result1>, <result2>) Apr 23, 2019
@matriv matriv merged commit add02f4 into elastic:master Apr 23, 2019
@matriv matriv deleted the impl-if branch April 23, 2019 13:30
matriv added a commit that referenced this pull request Apr 23, 2019
Implement a more trivial case of the CASE expression which is
expressed as a traditional function with 2 or 3 arguments. e.g.:

IIF(a = 1, 'one', 'many')
IIF(a > 0, 'positive')
Closes: #40917

(cherry picked from commit add02f4)
gurkankaymak pushed a commit to gurkankaymak/elasticsearch that referenced this pull request May 27, 2019
Implement a more trivial case of the CASE expression which is
expressed as a traditional function with 2 or 3 arguments. e.g.:

IIF(a = 1, 'one', 'many')
IIF(a > 0, 'positive')
Closes: elastic#40917
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SQL: Implement IIF conditional function
5 participants