【问题标题】:Distinct with select few columns doesn't work in JOOQ vs MySQL在 JOOQ 与 MySQL 中,选择少数列的区别不起作用
【发布时间】:2020-06-12 12:34:18
【问题描述】:

以下格式的 SQL 查询在 MySQL 中运行良好

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

在 jOOQ 中,我们可以在查询中使用 .selectDistinct 或选择字段但无法执行上述操作。

如果我选择 distinct(allfields),JOOQ 工作正常。但是,它在所有列中都是不同的,例如 distinct(emp.id)、distinct(emp.fname)、distinct(emp.name)

这是 JOOQ 中的一个错误,还是可以以相同的方式执行或将每个单独的列设置为不同的列以仅就一个列具有相同的性能?

请指教。

【问题讨论】:

    标签: java mysql sql jooq


    【解决方案1】:

    您认为您仅在一列上应用“独特功能”,但这不是您正在做的事情。您只是在第一列加上括号,就像您对所有其他列一样,即使没有distinct

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

    它没有任何作用,即使在 MySQL 中也是如此。 DISTINCT 子句仅适用于一列意味着什么?你会为其他列预测什么价值?一个随机的?例如:

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

    您希望只生产第一行还是只生产第二行?

    SQL 操作的逻辑顺序

    请注意,在 SQL 中,the logical order of operations 代表您的语句(假设语法):

    from employee
    select id, fname, name
    distinct
    

    换句话说,DISTINCT 操作“发生在”整个 SELECT 操作或投影之后。即使它似乎是SELECT 的一部分,但从语法上讲,它不是。我还在这篇关于 how DISTINCT and ORDER BY are related 的博文中对此进行了解释,这是 SQL 中另一个常见的混淆来源。

    按类别执行 TOP-1 查询的可预测方式

    如果您想根据IDFNAMENAME 生成随机值,可以使用以下语法:

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

    请注意,这些值不一定来自同一行。如果您希望它们来自同一行,则必须使用子查询或窗口函数来运行 TOP-1 per category query

    PostgreSQL DISTINCT ON

    请注意 PostgreSQL 为此目的支持DISTINCT ON,它与ORDER BY 一起决定应该从每个“不同组”中生成哪一行。我觉得这很令人困惑,但为了完整起见,在此提及。

    记录在案,I've answered this question also with a bit more detail here

    仍然在结果查询中获取这些括号

    如果出于某种原因,您选择不相信我,那么您可以随时使用 plain SQL 和 jOOQ 并在结果查询中强制使用这些括号:

    // 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();
    

    现在将按照您在问题中的要求输出。

    【讨论】:

    • 您希望只生产第一行还是只生产第二行?是的,只需要生产一排。无论是第一还是第二。没关系,它应该仅通过 id 找到唯一的。假设如果 id 不同,但是 f.name 相同..我希望 2 行而不是 1 行。不同的可以应用于一列或所有列。申请1列不同于申请所有列
    • @OdataDev:“distinct 可以应用于一列或所有列。申请 1 列与申请所有列不同” - 恐怕,这不是它的工作原理。没有区别。我挑战你证明你的主张 :-) 无论如何,我已经添加了更多代码来展示如何在生成的 jOOQ 查询中强制使用这些括号。
    猜你喜欢
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 2020-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    相关资源
    最近更新 更多