UNION和ORDER BY的使用不正确?

时间:2011-07-18 12:10:01

标签: mysql sql-order-by union

如何在mysql中使用 union 排序?

select * from _member_facebook 
inner join _member_pts 
ON _member_facebook._fb_owner=_member_pts._username 
where _member_facebook._promote_point = 9 
ORDER BY RAND() limit 2 
UNION ALL
select * from _member_facebook 
inner join _member_pts 
ON _member_facebook._fb_owner=_member_pts._username 
where _member_facebook._promote_point = 8 limit 3

给我错误

#1221 - Incorrect usage of UNION and ORDER BY

任何人都可以提供帮助吗?

7 个答案:

答案 0 :(得分:74)

尝试:

(
  select 
    * 
  from 
     _member_facebook 
   inner join 
     _member_pts 
   ON 
     _member_facebook._fb_owner=_member_pts._username 
  where 
    _member_facebook._promote_point = 9 
  ORDER BY RAND() 
  limit 2
) 
UNION ALL
(
  select 
    * 
  from 
    _member_facebook 
   inner join 
    _member_pts 
   ON 
     _member_facebook._fb_owner=_member_pts._username 
  where 
    _member_facebook._promote_point = 8 
  limit 3
)

虽然,我认为你应该将ORDER BY子句放在第二个查询的末尾

答案 1 :(得分:28)

括号:

(
    SELECT *
    FROM _member_facebook
    INNER JOIN _member_pts
    ON _member_facebook._fb_owner         =_member_pts._username
    WHERE _MEMBER_FACEBOOK._PROMOTE_POINT = 9
    ORDER BY RAND()
    LIMIT 2
)
UNION ALL
(
    SELECT *
    FROM _MEMBER_FACEBOOK
    INNER JOIN _MEMBER_PTS
    ON _MEMBER_FACEBOOK._FB_OWNER         =_MEMBER_PTS._USERNAME
    WHERE _MEMBER_FACEBOOK._PROMOTE_POINT = 8
    LIMIT 3
)

说,MySQL并不强制要求在外部子句中保留内部排序 - 虽然它可能这样做,因为它需要对行进行排序以计算相应的{{ 1}}条款。

答案 2 :(得分:22)

说明:

了解这是如何避免"陷阱"这一点非常重要。在类似的用例中。请注意,union的语法有些特殊":

  

子语句 union all 子语句 union all 子语句 [order by - clause] [limit - clause]

其中" 子语句"可以选择由()包围。一些工作示例:

  • select 1 union all (select 2);
    select 1 union all  select 2  union all (select 3);
    select 1 union all (select 2) union all  select 3;
    select 1 union all (select 2) union all (select 3);
    select 1 union all (select 2) union all (select 3) union all  select 4;
    select 1 union all (select 2) union all  select 3  union all (select 4);
    

然而,如果您包围第一个" 子语句"使用大括号,必须包围所有其他" 子语句" s括号:

  • (select 1) union all (select 2) union all (select 3);
    

(请注意,official docs中未提及上述要点。)

未能做到这一点是语法错误:

  • mysql> (select 1) union all select 2; -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error in your SQL syntax; check the...
    mysql> (select 1) union all (select 2) union all  select 3; -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error...
    mysql> (select 1) union all  select 2  union all (select 3); -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error...
    

接下来,每个" 子语句"可以包含wheregroup byhavingjoinlimit,但不能包含order by

如果您想使用order by,那么" 子语句"包含order by的{​​{1}}必须用大括号括起来。 (这意味着它们不再是可选的。)

现在,如果我们再次查看语法:

  

子语句 union all 子语句 union all 子语句 [order by - clause] [limit - clause]

我们可以看到整个union语句以可选order by / limit结尾。这两个关键字适用于整个union语句,而不仅仅是最后一个" 子语句":

  • mysql> select 1
        -> union all
        -> select 2 limit 1;
    +---+
    | 1 |
    +---+
    | 1 |
    +---+
    1 row in set (0.00 sec)
    
    mysql>
    

我们之前已经提到limit关键字也可以应用于个别" 子语句" s:

  • mysql> select 1 limit 1
        -> union all
        -> select 2;
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

如果您要将limit应用于最后一个" 子语句" (与整个union语句相对),必须包围最后一个" 子语句"括号:

  • mysql> select 1
        -> union all
        -> (select 2 limit 1);
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

limit应用于最后一个" 子语句" 以及到整个union语句,请使用:

  • mysql> select 1
        -> union all
        -> (select 2 limit 1)limit 1;
    +---+
    | 1 |
    +---+
    | 1 |
    +---+
    1 row in set (0.00 sec)
    
    mysql>
    

order by

相同
  • mysql> select 1
        -> union all
        -> (select 2 order by 1)order by 1;
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

但请注意,将order by应用于" 子语句" s 无意义因为文档已明确声明 order by只有在应用于整个union语句时才能保证(cf.):

  

–§– .. ORDER BY个人SELECT语句的使用并不代表行在最终结果中出现的顺序。

唯一的方式order by在" 子语句中有意义"如果你将它与limit结合使用:

  

–§– ..在此上下文中使用ORDER BY通常与LIMIT结合使用,因此它用于确定要为{{1}检索的所选行的子集},即使必然会影响最终SELECT结果中这些行的顺序。

此外,如果您想将select intoUNION结合使用,那么会有更多"陷阱"要小心。有关此问题,请参阅issue 32858

答案 3 :(得分:0)

正确的是:

(SELECT *
   FROM _member_facebook
   INNER JOIN _member_pts ON _member_facebook._fb_owner=_member_pts._username
   WHERE _member_facebook._promote_point = 9 LIMIT 2)
UNION ALL
  (SELECT *
   FROM _member_facebook
   INNER JOIN _member_pts ON _member_facebook._fb_owner=_member_pts._username
   WHERE _member_facebook._promote_point = 8 LIMIT 3)
ORDER BY 1

答案 4 :(得分:0)

尝试()我认为

(SELECT  CITY,LENGTH(CITY) FROM STATION WHERE LENGTH(CITY)=(SELECT MIN(LENGTH(CITY)) FROM STATION) ORDER BY CITY LIMIT 1) 
UNION ALL
(SELECT  CITY,LENGTH(CITY) FROM STATION WHERE LENGTH(CITY)=(SELECT MAX(LENGTH(CITY)) FROM STATION) ORDER BY CITY LIMIT 1);

答案 5 :(得分:0)

我认为如果您使用order by或limit或两者同时使用,则必须使用括号。我尝试通过不带括号的方式交替使用限制和顺序来处理查询,但该查询不起作用。只有在加上括号后才能起作用。

答案 6 :(得分:0)

在查询中使用Order by和limit子句时,使用括号解决了我的问题。我的要求是使表的顶部和底部行具有一定条件,并且以下代码对我有用:

(SELECT column1, column2
FROM table1
ORDER BY column1, column2
LIMIT 1)

UNION

(SELECT column1, column2
FROM table2
ORDER BY column1, column2 
LIMIT 1)