问题
This post comes as a result of a comment I left on a similar question: https://stackoverflow.com/a/19860271/2308858
I'm using PostgreSQL and jOOQ 3.4 and trying to represent the following SQL query in jOOQ:
SELECT *, COUNT(*) OVER()
FROM table1 t1
JOIN table2 t2 ON (t1.id = t2.id)
JOIN table3 t3 ON (t1.otherId = t3.otherId)
I like how Postgres lets me concisely represent "all columns plus the count
column" with nothing more than SELECT *, COUNT(*) OVER()
. But when I try to represent this same query in jOOQ, the most concise way I can do is:
create.select( TABLE1.fields() ).select( TABLE2.fields() ).select( TABLE3.fields() ).select( count().over() )
.from( TABLE1 )
.join( TABLE2 ).on( TABLE1.ID.equal( TABLE2.ID ))
.join( TABLE3 ).on( TABLE1.OTHER_ID.equal( TABLE3.OTHER_ID ))
Ideally, I'd write this instead:
create.select().select( count().over() )
.from( TABLE1 )
.join( TABLE2 ).on( TABLE1.ID.equal( TABLE2.ID ))
.join( TABLE3 ).on( TABLE1.OTHER_ID.equal( TABLE3.OTHER_ID ))
But this doesn't seem to work. Any thoughts on how I can do this?
回答1:
This solution, which you've found yourself, is indeed the way to go with the jOOQ API:
create.select( TABLE1.fields() )
.select( TABLE2.fields() )
.select( TABLE3.fields() )
.select( count().over() )
...
It conceptually corresponds to this valid SQL query:
SELECT table1.*, table2.*, table3.*, COUNT(*) OVER()
...
Manipulating the jOOQ "model API":
But if this is annoying to you, you can also work around this issue with this little trick:
// Get access to the "model API" from a statement without any SELECT fields
SelectQuery<?> select =
create.select()
.from( TABLE1 )
.join( TABLE2 ).on( TABLE1.ID.equal( TABLE2.ID ))
.join( TABLE3 ).on( TABLE1.OTHER_ID.equal( TABLE3.OTHER_ID ))
.getQuery();
// Copy all fields from the SELECT statement:
List<Field<?>> fields = new ArrayList<>(select.getSelect());
// And explicitly add them:
select.addSelect(fields);
select.addSelect(count().over());
This is equally verbose as your original attempt, but might be a bit simpler to use, generically.
Using a derived table
Of course, you could also simply write the following, equivalent SQL query, which would be more standard SQL:
SELECT t.*, COUNT(*) OVER()
FROM (
SELECT *
FROM table1 t1
JOIN table2 t2 ON (t1.id = t2.id)
JOIN table3 t3 ON (t1.otherId = t3.otherId)
) t
With jOOQ, this would translate to:
Table<?> t = select()
.from( TABLE1 )
.join( TABLE2 ).on( TABLE1.ID.equal( TABLE2.ID ))
.join( TABLE3 ).on( TABLE1.OTHER_ID.equal( TABLE3.OTHER_ID ))
.asTable("t");
create.select(t.fields(), count().over())
.from(t);
Support for the asterisk
In a future version of jOOQ, the actual asterisk (*) might be supported explicitly through the jOOQ API. At this point, it is a bit unclear how that can be achieved syntactically, though.
On a side-note:
I have always found it very curious that PostgreSQL allows this syntax here:
SELECT *, COUNT(*) OVER()
...
It is hardly ever supported by SQL engines and a bit "unpredictable". Neither does the SQL standard allow for a "standalone asterisk" to be combined with other column expressions.
来源:https://stackoverflow.com/questions/25313595/jooq-concisely-representing-both-columns-and-aggregate-window-functions-in-a-q