【问题标题】:where IN clause - multi column (querydsl)where IN 子句 - 多列(querydsl)
【发布时间】:2019-06-24 13:44:33
【问题描述】:

我有两对的三个整数值。
我想将其用作 WHERE 子句中的 IN 列表。

(2019, 5) (2019, 6) (2019, 7)

我想在这样的查询中使用上述两对列表:

SELECT
    *
FROM
    WEEK_REPORT A
WHERE
    A.user_id IN ('test2','test5' ) AND
    (A.year, A.week_no) IN ((2019,4),(2019,5),(2019,6));

为此,我将源码写如下:

// lastYear=2019, lastWeekNo=4
Tuple t = JPAExpressions.select(Expressions.constant(lastYear), Expressions.constant(lastWeekNo))
    .from(weekReport)
    .fetchOne();

// currentYear=2019, currentWeekNo=5        
Tuple t2 = JPAExpressions.select(Expressions.constant(currentYear), Expressions.constant(currentWeekNo))
    .from(weekReport)
    .fetchOne();

// nextYear=2019, nextWeekNo=4
Tuple t3 = JPAExpressions.select(Expressions.constant(nextYear), Expressions.constant(nextWeekNo))
    .from(weekReport)
    .fetchOne();

return queryFactory
    .select(weekReport)
    .from(weekReport)
    .where(weekReport.user.eq(user)
        .and(Expressions.list(weekReport.year, weekReport.weekNo).in(t, t2, t3)))
    .fetch();

但是没有输出正确的结果,出现错误。

java.lang.UnsupportedOperationException: null
    at com.querydsl.jpa.JPASubQuery.fetchOne(JPASubQuery.java:66) ~[querydsl-jpa-4.1.4.jar:na]

我在官方文档中查过,但没有出来。
有办法吗?

谢谢。

【问题讨论】:

  • 您可以将查询重写为AND ((A.year = 2019 AND A.week_no = 4) OR (A.year = 2019 AND A.week_no = 5) OR ...)
  • 什么版本的 MySQL? “行构造函数”在 5.7.3 版本之前优化不佳。

标签: mysql sql querydsl in-clause


【解决方案1】:
DECLARE @t TABLE (
  year int,
  week int
)
INSERT @t
  VALUES (2019, 4), (2019, 5), (2019, 6)

SELECT
  *
FROM WEEK_REPORT A
WHERE A.user_id IN ('test2', 'test5')
AND EXISTS (SELECT
  *
FROM @t T
WHERE A.year = T.year
AND T.week = A.week_no)

【讨论】:

    【解决方案2】:

    您要查找的内容有时称为行变量元组变量。您的 DBMS 可能没有这种生物。

    一般来说,IN 只是EXISTS 的简写,你可以给那只猫剥皮:

    SELECT * FROM WEEK_REPORT as A
    WHERE
    A.user_id IN ('test2','test5' )
    and exists (
        select 1 from (
            select 2019 as 'year', 4 as 'week'
            union
            select 2019, 5
            union
            select 2019, 6
            ) as T
        where week = A.week and year = A.year
    );
    

    还有其他方法。基本上,您希望将行变量放入某种表中,然后测试该表中是否存在。如果是我,并且年和周会随着时间变化,我会创建一个静态表来保存 3 行,这样我就可以在不更改查询的情况下修改搜索条件。

    【讨论】:

      【解决方案3】:

      如何将元组列表作为一个参数传递

      List<Tuple> params = ...
      
      params = [(2019,4),(2019,5),(2019,6)]
      
      return queryFactory
          .select(weekReport)
          .from(weekReport)
          .where(weekReport.user.eq(user)
              .and(Expressions.list(weekReport.year, weekReport.weekNo).in(params)))
          .fetch();
      

      【讨论】:

      • 你能显示params的例子吗,因为我出错了,我使用的是常量值
      【解决方案4】:

      试试这个

      SELECT
          *
      FROM
          WEEK_REPORT A
      WHERE
          A.user_id IN ('test2','test5' ) AND
          concat(A.year, A.week_no) IN (20194,20195,20196);
      

      【讨论】:

      • 其实我很想知道如何将IN子句中的多列表示为querydsl而不是原生sql。
      • 有一百种不同的软件包试图“帮助”用户说 SQL。大多数人都没有办法在不逃避“原生 SQL”的情况下做所有事情。 (我不能代表 querydsl。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 2013-05-31
      • 2018-07-19
      • 2011-10-18
      • 2011-05-16
      • 1970-01-01
      相关资源
      最近更新 更多