I have the ff. code.
#Override
public Optional<TransactionJournalRecord> findByReferenceNumber(final String referenceNumber) {
return this.dsl
.select(TRANSACTION_JOURNAL.fields())
.distinctOn(TRANSACTION_JOURNAL.CUSTOMER_NUMBER)
.from(TRANSACTION_JOURNAL)
.where(TRANSACTION_JOURNAL.REFERENCE_NUMBER.eq(referenceNumber))
.fetchOptionalInto(TransactionJournalRecord.class);
}
All I want it to do is to query a specific reference number but only getting the first distinct ref. no. as I want other duplicate transactions with the same ref no and customer number to be processed later on.
But I kept getting this error of
org.springframework.jdbc.BadSqlGrammarException: Access database using jOOQ; bad SQL grammar [select distinct on (`transaction_journal`.`customer_number`) `transaction_journal`.`id`, `transaction_journal`.`reference_number`, `transaction_journal`.`future_dated_transaction_id`, `transaction_journal`.`send_money_type_id`, `transaction_journal`.`source_account_number`, `transaction_journal`.`source_account_type`, `transaction_journal`.`customer_number`, `transaction_journal`.`request_id`, `transaction_journal`.`destination_account_number`, `transaction_journal`.`destination_account_type`, `transaction_journal`.`destination_validation`, `transaction_journal`.`transfer_schedule_type`, `transaction_journal`.`currency_id`, `transaction_journal`.`amount`, `transaction_journal`.`service_fee`, `transaction_journal`.`transaction_date`, `transaction_journal`.`posting_date`, `transaction_journal`.`status`, `transaction_journal`.`remarks`, `transaction_journal`.`created_date`, `transaction_journal`.`updated_date`, `transaction_journal`.`source_account_name`, `transaction_journal`.`username`, `transaction_journal`.`reason`, `transaction_journal`.`card_number`, `transaction_journal`.`status_remarks`, `transaction_journal`.`creditor_bank_code`, `transaction_journal`.`creditor_details`, `transaction_journal`.`mobile_number`, `transaction_journal`.`address`, `transaction_journal`.`channel_id`, `transaction_journal`.`system`, `transaction_journal`.`purpose_of_transaction`, `transaction_journal`.`esb_posted_date`, `transaction_journal`.`currency_id_destination`, `transaction_journal`.`gl_pa_status`, `transaction_journal`.`gl_sf_status`, `transaction_journal`.`gl_status_remarks`, `transaction_journal`.`email_address`, `transaction_journal`.`exchange_rate`, `transaction_journal`.`contact_type`, `transaction_journal`.`contact_value`, `transaction_journal`.`is_validated` from `transaction_journal` where `transaction_journal`.`reference_number` = ?]; nested exception is java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'on (`transaction_journal`.`customer_number`) `transaction_journal`.`id`, `transa' at line 1
at org.jooq_3.11.12.MYSQL_8_0.debug(Unknown Source)
Using DISTINCT ON
You're not using DISTINCT, you're using DISTINCT ON, which is a PostgreSQL vendor specific SQL feature. In newer versions of jOOQ, DISTINCT ON is being emulated using window functions for other dialects, so you might want to upgrade.
You'll still need an ORDER BY clause for DISTINCT ON to work. It's a bit of an esoteric PostgreSQL invention, adding to the confusion of the logical order of operations in SQL.
Using LIMIT
While what you want to do is possible with DISTINCT ON, it seems overly complicated. Here's a much simpler way to solve your problem, producing an arbitrary record, or optionally, if you uncomment the ORDER BY clause, the first/last record given some ordering:
SELECT *
FROM transaction_journal
WHERE transaction_journal.reference_number = :referenceNumber
-- ORDER BY something
LIMIT 1
With jOOQ:
#Override
public Optional<TransactionJournalRecord> findByReferenceNumber(
final String referenceNumber
) {
return this.dsl
.selectFrom(TRANSACTION_JOURNAL)
.where(TRANSACTION_JOURNAL.REFERENCE_NUMBER.eq(referenceNumber))
// .orderBy(something)
.limit(1)
.fetchOptional();
}
Using GROUP BY
Note that in MySQL, if strict mode is turned off, then the GROUP BY approach you've mentioned in your comments will also produce an arbitrary value for all non-GROUP BY columns, which is not correct standard SQL.
Unlike as with DISTINCT ON or LIMIT, you have no control over which value is being produced. As a matter of fact, you can't even be sure if two non-GROUP BY values belong to the same record. It is never a good idea to depend on this outdated, MySQL-specific behaviour.
Using DISTINCT
There is no way to solve this with DISTINCT only. If you don't have a unique constraint on your search criteria, then you will always get duplicates, which will throw an exception when using fetchOptional(), in jOOQ.
Is there another way to assign incremental values on a column without using the Windowed Function Row_Number() and Rank() in Google BigQuery.
Im actually encountering resource problems when using these functions
Thanks for the answer
Hi is there a way to programmatically detect if a query string is in the legacy or SQL-2011 syntax? I know the former uses [project:dataset.table] for table references while the later uses `project.dataset.table` but this doesn't seem very bullet proof.
There's no way to tell just from the query text in all cases, which is why BigQuery has the "Use Legacy SQL" checkbox in the UI and the use_legacy_sql option for the query API. For example, consider this query:
SELECT *
FROM (SELECT 1 AS x), (SELECT 2), (SELECT 3);
The results are very different despite the query being valid in both dialects.
Standard SQL queries can still contain [], too, such as for array literals.
Assuming query is syntax-wise correct and expected to actually work - you can do Dry Run using both options (Legacy and Standard) and see which fails and which not. Based on result you can potentially derive the answer
I am using an embedded Apache Derby database and execute the following query:
SELECT
someUniqueValue,
row_number() over(ORDER BY someUniqueValue) as ROWID
FROM
myTable;
someUniqueValue is a varchar.
I am getting the Exception:
java.sql.SQLFeatureNotSupportedException: Feature not implemented: WINDOW/ORDER BY
If i change the row_number() line in my query to:
row_number() over() as ROWID
The query runs fine (although the result is useless for me).
The Derby documentation states this is supported. What am I doing wrong?
The link you posted is just a draft to specify how the feature should be implemented.
If you scroll down a bit you find:
An implementation of the ROW_NUMBER() window function is included in Derby starting with the 10.4.1.3 release. Limitations and usage description may be found in the Derby Reference Manual
When you then look at Derby manual (your link is not the manual) http://db.apache.org/derby/docs/10.10/ref/rreffuncrownumber.html you'll find a list of limitations:
Derby does not currently allow the named or unnamed window specification to be specified in the OVER() clause, but requires an empty parenthesis. This means the function is evaluated over the entire result set.
The ROW_NUMBER function cannot currently be used in a WHERE clause.
Derby does not currently support ORDER BY in subqueries, so there is currently no way to guarantee the order of rows in the SELECT subquery. An optimizer override can be used to force the optimizer to use an index ordered on the desired column(s) if ordering is a firm requirement.
So I came across the following at work, and I can tell right away what it's for but I want to find any documentation for it and can't find anything online!
with details as
(
select *,
row_number() over (order by CREATED_DATE) as [Row]
from
(
select top 10 * from MyTable
) t
)
select *
from details
where [Row] > #lowLimit and [Row] < #highLimit
This looks to me like its for paging functionality. However, I don't know exactly what structure I'm looking at within the sql syntax. Does anyone recognize this syntax and can you point me to where I can read more about it?
Thanks!
That's a common table expression. These are used as temporary result sets for single queries. They are treated by the following query much like a view. You can do some neat stuff with them, like recursion!
Here's a brief description of their functionality from the link:
Create a recursive query.
Substitute for a view when the general use of a view is not required; that is, you do not have to store the definition in metadata.
Enable grouping by a column that is derived from a scalar subselect, or a function that is either not deterministic or has external access.
Reference the resulting table multiple times in the same statement.
Regarding semicolons, please check out this answer for a really useful tip - why you should always preface CTEs with semicolons.