UNION 和 ORDER BY 的使用不正确?
Posted
技术标签:
【中文标题】UNION 和 ORDER BY 的使用不正确?【英文标题】:Incorrect usage of UNION and ORDER BY? 【发布时间】:2011-10-07 15:22:59 【问题描述】:如何在mysql中使用union和order by?
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
有人可以帮忙吗?
【问题讨论】:
【参考方案1】:在查询中使用 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)
【讨论】:
【参考方案2】:我认为如果您使用 order by 或 limit 或同时使用两者,则必须使用括号。我尝试通过在不带括号的情况下互换使用限制和顺序来处理查询,但查询不起作用。它只有在添加括号后才有效。
【讨论】:
【参考方案3】:try () 我觉得像
(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);
【讨论】:
【参考方案4】:正确的是:
(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
【讨论】:
【参考方案5】:说明:
了解其工作原理对于避免在类似用例中出现“陷阱”非常重要。注意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);
但是,如果您用大括号将第一个“子语句”括起来,则您必须将所有其他“子语句”括起来 em>"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...
接下来,每个“子语句”可以包含where
、group by
、having
、join
、limit
,但不能包含order by
。
如果您想使用order by
,则包含order by
的“子语句”必须用大括号括起来。 (这意味着它们不再是可选的。)
现在,如果我们再看一下语法:
子语句
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
关键字也可以应用于单个“子语句”:
mysql> select 1 limit 1
-> union all
-> select 2;
+---+
| 1 |
+---+
| 1 |
| 2 |
+---+
2 rows in set (0.00 sec)
mysql>
如果您想将limit
应用于最后一个“子语句”(而不是整个union
语句),您必须将最后一个“substatement" 带大括号:
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
应用于“子语句”是没有意义的,因为文档明确声明 order by
只是保证 (cf.) 在应用于整个 union
语句时工作:
 –§– ..将
ORDER BY
用于单个SELECT
语句并不意味着行在最终结果中出现的顺序。
order by
在“子语句”中有意义的唯一方法是将它与 limit
结合使用:
 –§– ..在这种情况下 ORDER BY 的使用通常与
LIMIT
结合使用,因此它用于确定要为SELECT
检索的选定行的子集,即使它不一定会影响这些行在最终UNION
结果中的顺序。
此外,如果您想将select <strong><em>into</em></strong>
与union
结合使用,则需要注意更多“陷阱”。请参阅issue 32858 了解此内容。
【讨论】:
【参考方案6】:带括号:
(
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 在外部子句中保留内部排序并不是强制性的——尽管它可能会这样做,因为它无论如何都需要对行进行排序以计算相应的 @987654322 @ 子句。
【讨论】:
是的,我也错过了括号,并添加它修复它【参考方案7】:尝试:
(
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
子句放在第二个查询的末尾
【讨论】:
以上是关于UNION 和 ORDER BY 的使用不正确?的主要内容,如果未能解决你的问题,请参考以下文章
ORACLE 两个order by的SQL使用 UNION 或者 UNION ALL 报错 ORA-00933:sql命令未正确结束
oracle 两个sql带有order by的使用union/union all的时候报错 'ORA-00933:sql命令未正确结束' 处理办法