Select Distinct Not working in Spring with DSL Context

Posted

技术标签:

【中文标题】Select Distinct Not working in Spring with DSL Context【英文标题】: 【发布时间】:2021-09-24 01:18:24 【问题描述】:

我有 ff。代码。

 @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);
    

我想要它做的只是查询一个特定的参考号,但只获得第一个不同的参考。不。因为我希望稍后处理具有相同参考编号和客户编号的其他重复交易。

但我一直收到这个错误

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)

【问题讨论】:

如果您从异常中获取 SQL 语句,您是否能够以原始形式执行该语句?对我来说,这两个语句之间似乎缺少逗号(transaction_journal.customer_number) transaction_journal.id 哦,关于那个逗号的事情,我更新了帖子,因为当我把它变成某种引用时,它显然改变了格式。顺便说一句,我尝试执行 spring 生成的 sql 查询,并在 MySQL 工作台中得到了同样的错误。是否需要更新某些内容以更改版本才能使其正常工作,或者这是我的代码中的错误?我不太熟悉为什么它不起作用,因为 DSL 上下文似乎支持它。 如果不使用.Select,然后使用.DistinctOn,而是使用. selectDistinct(TRANSACTION_JOURNAL.fields()).asList(),会怎样?这行得通吗? 没用,.asList() 出错了。 如何用在工作台中执行的普通 SQL 编写查询? 【参考方案1】:

使用DISTINCT ON

您使用的不是DISTINCT,而是DISTINCT ON,这是PostgreSQL 供应商特定的SQL 功能。 In newer versions of jOOQ, DISTINCT ON is being emulated using window functions for other dialects,所以你可能想要升级。

您仍然需要一个 ORDER BY 子句才能使 DISTINCT ON 起作用。这是一个有点深奥的 PostgreSQL 发明,增加了the logical order of operations in SQL 的混乱。

使用LIMIT

虽然DISTINCT ON 可以实现您想要做的事情,但它似乎过于复杂。这是解决问题的一种更简单的方法,可以生成任意记录,或者如果您取消注释 ORDER BY 子句,则可以选择第一个/最后一个记录给定一些顺序:

SELECT *
FROM transaction_journal
WHERE transaction_journal.reference_number = :referenceNumber
-- ORDER BY something
LIMIT 1

使用 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();

使用GROUP BY

请注意,在 MySQL 中,如果 strict mode is turned off,那么您在 cmets 中提到的 GROUP BY 方法也会为所有非 GROUP BY 列生成一个任意值,即不正确的标准 SQL。

DISTINCT ONLIMIT 不同,您无法控制生成的值。事实上,您甚至无法确定两个非GROUP BY 值是否属于同一记录。依赖这种过时的、特定于 MySQL 的行为绝不是一个好主意。

使用DISTINCT

仅使用DISTINCT 无法解决此问题。如果您对搜索条件没有唯一约束,那么您将始终得到重复项,这将在 jOOQ 中使用 fetchOptional() 时引发异常。

【讨论】:

嗨,我自己还没有尝试过,但是阅读此内容现在使其更加清晰,并且似乎可以工作。下次遇到这种情况时,我将尝试 jooq 中的建议,因为目前,我已经使用 groupby 语法提升了我的更改,该语法到目前为止已通过我的测试。非常感谢您清理它。我只是有点知道我可能会错误地使用 distinct ,这很好地解释了这一点。伟大的。 ♥

以上是关于Select Distinct Not working in Spring with DSL Context的主要内容,如果未能解决你的问题,请参考以下文章

sql中select distinct id和select distinct *之间的区别

二,本章讲解 SELECT DISTINCT 语句(distinct)

SQL SELECT DISTINCT 语句

SQL SELECT DISTINCT 语句 用法

SQL SELECT DISTINCT 语句

为啥“SELECT DISTINCT a, b FROM...”返回的记录少于“SELECT DISTINCT A + '|' + B 来自...”?