简体   繁体   中英

Distinct with select few columns doesn't work in JOOQ vs MySQL

The below format of SQL query works fine in MySQL

select distinct(emp.id), emp.fname, emp.name from employee emp;

in jOOQ we can either use .selectDistinct in the query or select the fields but unable to do the above.

If I do select distinct(allfields), JOOQ works fine. However, it does distinct in all the columns such as distinct(emp.id), distinct(emp.fname), distinct(emp.name)

Is it a bug in JOOQ or is it possible to execute in the same fashion or putting distinct with each individual column to have the same performance with respect to one column alone?

Please advise.

You're thinking that you're applying the "distinct function" only on one column, but that's not what you're doing. You're just parenthesising your first column, as you could have done with all the others, and even without distinct

select (emp.id), (emp.fname), (((emp.name))) from employee emp;

It has no effect, even in MySQL. What would it even mean for the DISTINCT clause to apply to only one column? What value would you project for the other columns? A random one? For example:

+----+-------+------+
| ID | FNAME | NAME |
+----+-------+------+
|  1 | A     | A    |
|  1 | B     | B    |
+----+-------+------+

Is your expectation to produce only the first or only the second row?

Logical order of SQL operations

Notice that in SQL, the logical order of operations is, for your statement (in hypothetical syntax):

from employee
select id, fname, name
distinct

In other words, the DISTINCT operation "happens after" the entire SELECT operation, or projection. Even if it seems to be part of SELECT , syntactically, it is not. I have also explained this in this blog post about how DISTINCT and ORDER BY are related , which is another popular source of confusion in SQL.

A predictable way to perform TOP-1 per category queries

If you want to produce random values for FNAME and NAME per ID , you could use this syntax:

select id, max(fname), max(name)
from employee
group by id

Beware that the values wouldn't necessarily stem from the same row. If you want them to be from the same row, you'd have to use a subquery or window functions to run a TOP-1 per category query

PostgreSQL DISTINCT ON

Do note that PostgreSQL supports DISTINCT ON for that purpose, which works together with ORDER BY to decide which row should be produced from each "distinct group". I find that very confusing, but mentioned it here for completeness' sake.

For the record, I've answered this question also with a bit more detail here .

Getting those parentheses in the result query nonetheless

If, for some reason, you choose to not believe me, then you can always resort to using plain SQL with jOOQ and force those parentheses in the resulting query:

// Static import is implied
import static org.jooq.impl.DSL.*;

ctx.selectDistinct(
        field("({0})", EMPLOYEE.ID.getDataType(), EMPLOYEE.ID),
        EMPLOYEE.FNAME,
        EMPLOYEE.NAME)
   .from(EMPLOYEE)
   .fetch();

The output will now be as you requested in your question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM