QueryDsl SQL — левое присоединение к подзапросу

Я использую QueryDsl SQL и хочу left join подзапрос. Вот простой запрос SQL

SELECT
  usr.memberId,
  payoutsBbf.totalPyts
FROM
  users usr
  LEFT JOIN
    (SELECT
       pyt.member_id   AS mmb_id,
       SUM(pyt.amount) AS totalPyts
  FROM
    payout pyt
  WHERE
    pyt.payoutPeriod < '2018-01-01'
    GROUP BY pyt.member_id) AS payoutsBbf ON usr.id = payoutsBbf.mmb_id

Я хочу написать это в QueryDsl SQL, и почти важно, чтобы подзапрос оставался присоединенным к основной таблице users, потому что это всего лишь фрагмент всего сложного запроса.

  1. Как мне быть с частью LEFT JOIN x ON

  2. Как мне работать с псевдонимом подзапроса в части SELECT payoutBbf.totalPyts

.leftJoinquerydsl.com/static/querydsl/latest/reference/html/…
spencer7593 08.04.2019 21:21

Проблема здесь в том, что я leftJoin-ingQUsers для подзапроса. С Q-классом я могу использовать точечную нотацию для записи .leftJoin(subquery).on(qusers.id.eq(??), но я столкнулся с проблемой в части подзапроса on

Kihats 08.04.2019 21:31

Ответ на похожий вопрос: stackoverflow.com/a/67254869/3308908

GauravRatnawat 25.04.2021 17:14
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
5 361
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, это сработает для вас. Это немного взломано:

SQLQueryFactory sqlqf; // Should be @Autowired

QUsers qusers = new QUsers();
QPayouts qpayouts = new QPayouts();

Expression<Long> memberId = ExpressionUtils.as(qpayouts.memberId, "mmb_id");
Expression<Double> totalPayouts = ExpressionUtils.as(qpayouts.amount.sum(), "totalPayouts");

SQLQuery<Tuple> payoutsBbf = SQLExpressions.select(memberId, totalPayouts)
            .from(qpayouts)                
            .where(qpayouts.payoutPeriod.lt("2018-01-01")) // Use date object
            .groupBy(qpayouts.memberId);

final SimplePath<? extends SQLQuery> payoutsBBfPath = Expressions.path(payoutsBBfPath.getClass(), "payoutsBbf");

List<Tuple> fetch = sqlqf.select(
        qusers.memberId,                
        Expressions.path(payoutsBbf.getClass(), new PathMetadata(payoutsBBfPath, "totalPayouts", PathType.PROPERTY))
    )
    .from(qusers)
    .leftJoin(payoutsBbf, payoutsBBfPath)
    .addJoinFlag(" on payoutsBbf.mmb_id = users.id", JoinFlag.Position.BEFORE_CONDITION)
    .fetch();

Обратите внимание на использование JoinFlag для указания столбца соединения с использованием псевдонима, определенного как payoutsBbf. Также обратите внимание на использование Expressions.path() для указания подстолбцов в разделе select().

что такое groupBy.getClass()?

raven 30.05.2019 13:05

Это должно быть payoutsBBfPath.getClass() , я отредактировал ответ, чтобы отразить это

maxuville 30.05.2019 14:36

какая это версия? Я не могу найти addJoinFlag метод

Rookie007 25.09.2019 06:22

Использование версии 4.2.1

maxuville 25.09.2019 10:00
Ответ принят как подходящий

вот как бы я это сделал:

final StringPath payoutsBbf = stringPath("payoutsBbf");
final String mmbId = "mmb_id";
final String totalPyts = "totalPyts";
sqlQueryFactory.select(users.memberId, stringPath(payoutsBbf, totalPyts))
    .from(users).leftJoin(
        sqlQueryFactory.select(payout.member_id.as(mmbId), member_id.amount.sum().as(totalPyts))
            .from(payout).where(payout.payoutPeriod.lt("2018-01-01")).groupBy(payout.member_id),
        payoutsBbf
    ).on(users.id.eq(stringPath(payoutsBbf, mmbId))).fetch();

Это было очень просто. Вы спасатель жизни. Спасибо

Kihats 11.01.2021 12:03

Для тех, кому интересно, как был создан StringPath: Expressions.stringPath("payoutBbf");Expressions.stringPath(payoutBbf, totalPyts) ... а также, поскольку users.id является NumberPath<Long>, используйте это: Expressions.numberPath(Long.class, payoutBbf, mmbId)

Kihats 11.01.2021 12:11

Как это вообще компилируется? Это все еще возможно в querydsl 5? Помещение подзапроса в качестве аргумента в leftJoin с кортежем заканчивается Cannot resolve method 'leftJoin(com.querydsl.jpa.JPQLQuery<T>, com.querydsl.core.types.dsl.StringPath)'

nailer_boxer 18.02.2022 19:24

@nailer_boxer Я некоторое время не работал с querydsl, поэтому мне потребовалось бы много времени, чтобы протестировать его; но из вашей ошибки кажется, что вы используете querydsl с JPA; Я не использовал JPA.

raven 19.02.2022 09:11

@raven, да, я использую его с JPA, так что, думаю, проблема в этом. В любом случае, спасибо :). Я нашел другое решение, которое меня устраивает. Я опубликую его, может быть, завтра, если у меня будет время, на случай, если кто-то еще борется с этим.

nailer_boxer 20.02.2022 02:55

Другие вопросы по теме