【问题标题】:Translate MYSQL query to HQL using multiple JOINS使用多个 JOINS 将 MYSQL 查询转换为 HQL
【发布时间】:2017-12-11 23:35:52
【问题描述】:

每个人。

我正在使用 grails 3.3.0.M2 框架和 mysql 作为数据源,以下 sql 查询按预期工作

SELECT 
    c.name,
    SUM(CASE
        WHEN t.status = 'open' THEN 1
        ELSE 0
    END) 'open',
    SUM(CASE
        WHEN t.status = 'pending' THEN 1
        ELSE 0
    END) 'in progress',
    SUM(CASE
        WHEN t.status = 'closed' THEN 1
        ELSE 0
    END) 'closed'
FROM
    tickets t
        INNER JOIN
    users u ON t.user_id = u.id
        INNER JOIN
    user_coordinations uc ON uc.user_id = u.id
        INNER JOIN
    coordinations c ON c.id = uc.coordination_id
GROUP BY 1

我使用隐式 JOIN 翻译成 HQL 但我得到了错误的结果,这里是 hql 查询:

SELECT 
    c.name,
    SUM(CASE
        WHEN t.status = 'open' THEN 1
        ELSE 0
    END),
    SUM(CASE
        WHEN t.status = 'pending' THEN 1
        ELSE 0
    END),
    SUM(CASE
        WHEN t.status = 'closed' THEN 1
        ELSE 0
    END)
FROM
    Ticket t, User u, UserCoordination uc, Coordination c
WHERE
    MONTH(t.dateCreated) = :month
GROUP BY 1

为了得到正确的结果堆栈溢出用户帮助我理解查询需要使用显式连接,这里的问题是:Group by a field that does not belongs to the consulted table

现在我正在尝试以下查询:

SELECT 
    c.name,
    SUM(CASE
        WHEN t.status = 'open' THEN 1
        ELSE 0
    END),
    SUM(CASE
        WHEN t.status = 'pending' THEN 1
        ELSE 0
    END),
    SUM(CASE
        WHEN t.status = 'closed' THEN 1
        ELSE 0
    END)
FROM
    Ticket t
        INNER JOIN
    User u
        INNER JOIN
    UserCoordination uc
        INNER JOIN
    Coordination c
WHERE
    MONTH(t.dateCreated) = :month
GROUP BY 1

但我收到 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException 并带有导致的消息 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“inner join user_coordinations usercoordi2_ on inner join coordinates coordinat”附近使用正确的语法

感谢您的帮助和时间

【问题讨论】:

    标签: mysql sql grails hql grails-orm


    【解决方案1】:
    SELECT new map(
        c.name as name,
    (CASE
            WHEN t.status = 'open' THEN 1
            ELSE 0
        END) as open,
    (CASE
            WHEN t.status = 'pending' THEN 1
            ELSE 0
        END) as pending, 
    (CASE
            WHEN t.status = 'closed' THEN 1
            ELSE 0
        END) as closed,
        SUM(open) as openSum,
        SUM(pending) as pendingSum,
        SUM(closed) as closedSum
    )
    FROM
        Ticket t
            left join t.user u left join u.userCoordination uc left join uc.coordination c 
    WHERE
        MONTH(t.dateCreated) = :month
    

    //按 1 分组

    你在上面缺少的东西更像是你需要的,你需要的 select new map(i.item as item... 如果您将此基础知识与您所拥有的以及我尝试做的进行比较,您就会明白为什么会出现错误。

    不确定你的 group by 它应该是 group by something。不确定内连接是否只是指连接,如果是这种情况,则忽略所有左连接,因为左连接尝试连接并获取任何空的 hasMany 关系等。

    【讨论】:

    • 感谢您回答@vahid。 SELECT NEW ... 对我来说是新的。我可以看到查询构造的优势。关于这个问题,我收到了一个 org.hibernate.QueryException 导致的消息:could not resolve property: userCoordination of: ni.edu.ucc.leon.User跨度>
    • 我认为这是因为用户和协调之间存在一对多的关联。我如何在查询中表达这一点?这个位置有一个 SQL Fiddle:sqlfiddle.com/#!9/9ed08/1
    • @yuor 第一个问题你有UserCoordination 我不知道你的域对象映射是什么。所以如果User hasMany = [ ucord:UserCoordination] 那将是left join u.ucord uc,这就是你在域对象中声明的映射。关于您的第二个问题,left join 可以满足您的第二个问题,其中某些内容为空或某些内容具有某些价值,这将涵盖所有内容。如果您从join 中省略了left 单词,那么它将列出1 条记录。所以当 left join 并且 user1 有两条记录时,它会出现两次
    • 我的错误@vadin 它是用户和协调之间的多对多关联。所以 UserCoordination 是数据透视表。这就是为什么我在u.UserCoordination 中收到错误消息。对不起,我没有正确解释自己
    • 我认为这并不重要,注意骆驼案u.UserCoordination vs u.userCoordination 我在给出的答案中故意犯了错误/区别,因为我看不到你是如何声明的你的关系。如果你有hasMany = [ userCoordination:UserCoordination],那么正确的是上面的vs中的后者
    猜你喜欢
    • 2020-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-27
    • 2016-09-22
    • 2013-07-02
    • 2014-06-26
    • 1970-01-01
    相关资源
    最近更新 更多