【问题标题】:Error with ORDER BY clause using UNION in MySQL在 MySQL 中使用 UNION 的 ORDER BY 子句出错
【发布时间】:2018-11-28 21:10:26
【问题描述】:

我在 MySQL 中有以下查询:

(SELECT ue.id, ue.userid, ue.status, ue.timestart, ue.timeend, e.courseid,
        e.id AS enrolid, ra.roleid
 FROM user_enrolments ue
 JOIN enrol e ON e.id = ue.enrolid
 JOIN course c ON c.id = e.courseid
 JOIN user u ON u.id = ue.userid
 JOIN context ct ON ct.instanceid = c.id
 LEFT JOIN role_assignments ra ON ra.userid = u.id AND 
                               ra.contextid = ct.id AND
                               ra.itemid = e.id
 WHERE e.customint1 = 1 AND u.deleted = 0 AND 
       ct.contextlevel = 50 AND (ue.status = 0 OR ue.status = 1)) 

UNION

(SELECT de.enrolid AS id, de.userid, de.status, de.date_ini, de.date_fin, 
        de.courseid, de.enrolid, de.roleid
 FROM deleted_enrols de
 JOIN user u ON u.id = de.userid
 WHERE userid = ANY (SELECT userid FROM local_users WHERE clientid = 1))

ORDER BY u.firstname, u.lastname, c.fullname LIMIT 0, 100

如果我删除 ORBER BY 和 LIMIT,这个查询可以正常工作...但是 ORDER BY 子句给出错误:

Table 'u' from one of the SELECTs cannot be used in global ORDER clause

如果我删除两个 SELECT 查询的括号,错误是不同的:

Table 'u' from one of the SELECTs cannot be used in field list

我也尝试过 UNION ALL,但它也不起作用。

有什么建议或线索吗?提前感谢您的宝贵时间...

【问题讨论】:

  • 问题在于别名的范围。 “U”在您尝试使用它的地方不存在。

标签: mysql sql sql-order-by union


【解决方案1】:

UNION 的结果不包含表“u”中的任何字段,因此这些结果无法按表“u”字段排序。

您也许可以执行 UNION,然后将结果重新连接到表 'u',然后使用它按表 'u' 字段对结果进行排序。排序存在类似的问题 course.fullname,所以也需要重新加入。

SELECT x.id, x.userid, x.status, x.timestart, x.timeend, x.courseid, x.enrolid, x.roleid
FROM ((SELECT ue.id, ue.userid, ue.status, ue.timestart, ue.timeend, e.courseid,
        e.id AS enrolid, ra.roleid
       FROM user_enrolments ue
         JOIN enrol e ON e.id = ue.enrolid
         JOIN course c ON c.id = e.courseid
         JOIN user u ON u.id = ue.userid
         JOIN context ct ON ct.instanceid = c.id
         LEFT JOIN role_assignments ra ON ra.userid = u.id 
           AND ra.contextid = ct.id 
           AND ra.itemid = e.id
       WHERE e.customint1 = 1 AND u.deleted = 0 
           AND ct.contextlevel = 50 AND (ue.status = 0 OR ue.status = 1)) 
       UNION
       (SELECT de.enrolid AS id, de.userid, de.status, de.date_ini, de.date_fin, 
        de.courseid, de.enrolid, de.roleid
        FROM deleted_enrols de
          JOIN user u ON u.id = de.userid
         WHERE userid = ANY (SELECT userid FROM local_users WHERE clientid = 1))
) x
  JOIN user z ON z.id = x.userid
  JOIN course d ON d.id = x.courseid
ORDER BY z.firstname, z.lastname, d.fullname LIMIT 0, 100

【讨论】:

  • 非常感谢...我在第一个选择中添加了“x.id”,因为我收到一条消息警告说“id”列不明确,现在可以正常工作了...跨度>
  • 当然。抱歉,我在整理我的答案时没有注意到这一点。我会调整的。
  • 我意识到我添加了两次id 列,并且应该只添加一次。我已更新我的答案以删除第二个 id 并将表别名添加到第一个 SELECT 中的所有字段。
【解决方案2】:

正如union 上的 mysql 文档所说:

这种 ORDER BY 不能使用包含 表名(即 tbl_name.col_name 格式的名称)。反而, 在第一个 SELECT 语句中提供一个列别名并参考 ORDER BY 中的别名。 (或者,请参阅 ORDER BY 使用其列位置。但是,使用列位置 已弃用。)

此外,如果要排序的列具有别名,则 ORDER BY 子句必须 引用别名,而不是列名。

因此,不要引用任何表名并使用实际在联合结果集中的列。

【讨论】:

    【解决方案3】:

    假设您要对整个批次进行排序,请尝试在整个查询中加上括号,然后执行 ORDER BY:

    select id, userid, status, timestart, timeend, courseid, enrolid, roleid from
    ((SELECT ue.id, ue.userid, ue.status, ue.timestart, ue.timeend, e.courseid,
            e.id AS enrolid, ra.roleid, u.firstname, u.lastname, c.fullname
     FROM user_enrolments ue
     JOIN enrol e ON e.id = ue.enrolid
     JOIN course c ON c.id = e.courseid
     JOIN user u ON u.id = ue.userid
     JOIN context ct ON ct.instanceid = c.id
     LEFT JOIN role_assignments ra ON ra.userid = u.id AND 
                                   ra.contextid = ct.id AND
                                   ra.itemid = e.id
     WHERE e.customint1 = 1 AND u.deleted = 0 AND 
           ct.contextlevel = 50 AND (ue.status = 0 OR ue.status = 1)) 
    
    UNION
    
    (SELECT de.enrolid AS id, de.userid, de.status, de.date_ini, de.date_fin, 
            de.courseid, de.enrolid, de.roleid, u.firstname, u.lastname, ' ' as fullname
     FROM deleted_enrols de
     JOIN user u ON u.id = de.userid
     WHERE userid = ANY (SELECT userid FROM local_users WHERE clientid = 1))) s1
    
    ORDER BY firstname, lastname, fullname LIMIT 0, 100
    

    (显然,第二个 SELECT 语句中的全名会被填充,但看起来很明智)

    【讨论】:

      【解决方案4】:

      您需要在联合查询的选择中包含要排序的数据; UNION 之后的 ORDER BY 被处理就像它是SELECT * FROM (unions) ORDER BY ...,所以任何不是来自联合的东西都不能用于排序。

      具有讽刺意味的是,与此类似的查询是获得所需内容的关键,例如

      SELECT x, y, z
      FROM (
      SELECT x, y, z, somethingIdontactuallywant
      FROM blah
      UNION
      SELECT a, b, c, somethingIdontactuallywant
      FROM blah2
      ) AS u
      ORDER BY u.somethingIdontactuallywant
      

      【讨论】:

        猜你喜欢
        • 2011-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-30
        • 1970-01-01
        相关资源
        最近更新 更多