简体   繁体   中英

Jooq- Left inner join

I am trying to query my task_template table where the task_Template.id.in(1,4) with an inner join on the task table where task.task_Template_id.eq(task_template.id). So I want to return all template rows where id is 1 or 4, and the task for that template if it exists.

I have two templates in my DB, with one task with task_template_id of 1.

So I am trying to return two templates, where the task will be null in one and populated in the other.

however my query seems to be doing an inner join and only returning one result?

    var query =
    dsl.select(TASK_TEMPLATE.fields())
        .select(TASK.fields())
        .from(TASK_TEMPLATE)
        .leftJoin(TASK)
        .on(TASK_TEMPLATE.ID.eq(TASK.TASK_TEMPLATE_ID))
        .where(TASK_TEMPLATE.TENANT.eq(TenantContext.getCurrentTenant()))
            .and(TASK_TEMPLATE.ID.in(rootTemplateIds))
        .and(TASK.ENTITY_NAME.eq(entityName))
        .and(TASK.ENTITY_ID.eq(entityId))
        .and(TASK.DELETED.eq(Boolean.FALSE))
        .orderBy(TASK.ORDER.asc().nullsLast());

You cannot write predicates like that on the TASK table when you left join it, otherwise, the effect will be that your left join turns into an inner join. This can be shown by example:

TASK_TEMPLATE

+----+--------+
| ID | TENANT |
+----+--------+
|  1 | A      |
|  2 | B      |
+----+--------+

TASK

+----------------+-------------+
| TASK_TENANT_ID | ENTITY_NAME |
+----------------+-------------+
|              1 | X           |
+----------------+-------------+

The result after a LEFT JOIN will be

+----+--------+----------------+-------------+
| ID | TENANT | TASK_TENANT_ID | ENTITY_NAME |
+----+--------+----------------+-------------+
|  1 | A      |              1 | X           |
|  2 | B      |                |             |
+----+--------+----------------+-------------+

Now, if you're filtering on ENTITY_NAME (and other fields), which may be NULL after your LEFT JOIN , then you will get the same effect as if you had inner joined them in the first place. You cannot filter columns from LEFT JOIN -ed tables in the WHERE clause.

Maybe, you intended to filter them in your ON clause instead (as a part of your LEFT JOIN operation):

var query =
dsl.select(TASK_TEMPLATE.fields())
    .select(TASK.fields())
    .from(TASK_TEMPLATE)
    .leftJoin(TASK)
    .on(TASK_TEMPLATE.ID.eq(TASK.TASK_TEMPLATE_ID))
    // Move these here
    .and(TASK.ENTITY_NAME.eq(entityName))
    .and(TASK.ENTITY_ID.eq(entityId))
    .and(TASK.DELETED.eq(Boolean.FALSE))
    .where(TASK_TEMPLATE.TENANT.eq(TenantContext.getCurrentTenant()))
        .and(TASK_TEMPLATE.ID.in(rootTemplateIds))
    // Remove them from here
    // .and(TASK.ENTITY_NAME.eq(entityName))
    // .and(TASK.ENTITY_ID.eq(entityId))
    // .and(TASK.DELETED.eq(Boolean.FALSE))
    .orderBy(TASK.ORDER.asc().nullsLast());

I've also discussed the difference between the ON and WHERE clauses in this blog post here .

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