在MySQL中使用UNION的ORDER BY子句错误

时间:2018-06-19 20:15:11

标签: mysql sql sql-order-by union

我在MySQL中有以下查询:

compileSdkVersion 27
targetSdkVersion 27

implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'

如果我删除ORBER BY和LIMIT,则此查询工作正常...但是ORDER BY子句给出了错误:

(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

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

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

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

有任何建议或线索吗?预先感谢您的宝贵时间...

4 个答案:

答案 0 :(得分:2)

假设您想对全部商品进行排序,请尝试用圆括号将整个查询括起来,然后再进行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语句中的全名将被填充,但似乎很明智)

答案 1 :(得分:2)

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

答案 2 :(得分:1)

您需要在联合查询的选择中包括要排序的数据;紧跟在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

答案 3 :(得分:0)

union上的mysql文档说:

  

这种ORDER BY无法使用包含以下内容的列引用   表名(即tbl_name.col_name格式的名称)。代替,   在第一个SELECT语句中提供列别名,并参考   ORDER BY中的别名。 (或者,请参阅   使用其列位置进行排序。但是,使用列位置   已弃用。)

     

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

因此,请勿引用任何表名,而应使用联合的结果集中实际存在的列。