2016-12-03 54 views
-1

我有以下的SQL语句:UNION ALL - > ORDER BY不按预期工作......?

(SELECT animation_id, 
      animation_name, 
      animation_group 
    FROM animations 
    WHERE animation_id = '45') 
UNION ALL 
    (SELECT animation_id, 
      animation_name, 
      animation_group 
    FROM animations 
    WHERE animation_id <> '45' 
    AND active = TRUE 
    ORDER BY animation_group, 
      animation_name) 

表看起来是这样的:

Table

的排序是不正常。我希望数据按“animation_group”列进行排序,但结果会在“animation_id”后面排序。 看截图,其中显示输出:

Sorting

如果是相关的:它是MySQL的。该声明是通过PHP调用的。

SQL语句是否正确?

谢谢!

编辑: 我的要求的基础或可以说,为什么我使用UNION是以下原因:

第一选择的结果应该永远是第一行。 第二个选择的结果应该按照。所以我不想要整个结果。

+0

尝试删除括号,以便对整个结果集使用“ORDER BY”。 –

回答

0

手动添加一个排序顺序所选项目:

SELECT 
    animation_id, 
    animation_name, 
    animation_group, 
    CASE WHEN animation_id = '45' THEN 1 ELSE 0 END AS is_selected 
FROM 
    animations 
WHERE 
    animation_id = '45' OR (animation_id <> '45' AND active = true) 
ORDER BY 
    is_selected DESC, 
    animation_group, 
    animation_name 

如果你仍然想保持你的UNION因为某些原因:

SELECT 
    animation_id, 
    animation_name, 
    animation_group, 
    1 AS is_selected 
FROM 
    animations 
WHERE 
    animation_id = '45' 
UNION ALL -- If animation_id is unique, I can't see why you'd need a UNION ALL here, by the way 
SELECT 
    animation_id, 
    animation_name, 
    animation_group, 
    0 AS is_selected 
FROM 
    animations 
WHERE 
    animation_id <> '45' AND 
    active = true 
ORDER BY 
    is_selected DESC, 
    animation_group, 
    animation_name 

此外,假设animation_id是唯一的整数,1 )你不需要UNION ALL,因为无论如何选择的每一行都是唯一的,并且2)你不需要围绕值的引号,即只需要animation_id = 45就行,而不是animation_id = '45'

+0

谢谢马特! - 它似乎与您的“CASE WHEN”解决方案完美配合。我以前从未使用过它。 您是否真的回答我以下问题: 我是否还需要“animation_id ='45'行(animation_id <>'45'AND active = true)”,为什么? 我想我只会需要active-clause? – Walhalla

+0

我认为只有你可以回答 - 我不知道你的'active'标志表示什么,或者它对于选定的动画可能不是真的,等等。你需要仔细考虑,也许可以尝试一些实验。 –

+0

你的解决方案工作绝对精细和防弹。我刚刚在我的项目中用“CASE WHEN ...”替换了所有类似UNION的:-) :-) :-) 我会考虑active-flag并对其进行测试。 – Walhalla

1

首先没有group by而是问题是order by。其次,不明白为什么你需要这里的UNION。你可以改变你的查询要像下面使用OR条件可能

SELECT animation_id, animation_name, animation_group 
FROM animations 
WHERE animation_id = '45' 
OR (animation_id <> '45' and active = true) 
ORDER BY animation_group, animation_name; 
+0

对不起 - 你说得对。我纠正了标题。 请求的基础是,所选值(在本例中为id = 45)将是结果中的第一行。 – Walhalla

+0

我个人总是喜欢在'WHERE'子句中放置'OR'的括号。在ORs操作符优先之前,我已经在WHERE的末尾添加了一个AND,并支付了AND的价格。 – Unoembre

0

试试这个

SELECT * FROM (
    SELECT animation_id, animation_name, animation_group 
    FROM animations 
    WHERE animation_id = '45' 
UNION ALL 
    SELECT animation_id, animation_name, animation_group 
    FROM animations 
    WHERE animation_id <> '45' and active = true 
) as tmp_table 
ORDER BY animation_group, animation_name; 
+0

对不起,我会更新请求。 请求的基础是,所选值(在本例中为id = 45)将是结果中的第一行。 随着您的声明,所有结果将被排序,所选值不再在第一行。 – Walhalla

0

只是不被括号内括起来的顺序。 这样做,仅执行第二个查询的顺序,而不是结果。而且,UNION可以自由地对结果进行重新排序。一个或多个UNION之后的订单适用于联合结果,但前提是您不使用括号更改其范围。 如果您删除括号,则您的查询将生效。

0

“UNION ALL - > ORDER BY无法按预期工作” - 事实上,它不是按预期工作,它正在为documented

个人SELECT语句使用的ORDER BY并不意味着要在最终结果中行出现的顺序,因为UNION默认情况下会生成无序的一组行。因此,在这种情况下使用ORDER BY通常与LIMIT一起使用,以便它用于确定为SELECT检索的选定行的子集,即使它不一定会影响最终的那些行的顺序UNION结果。如果ORDER BYSELECT中没有LIMIT而出现,则它会被优化掉,因为它无论如何都不会起作用。

要使用ORDER BYLIMIT条款进行排序或限制整个UNION结果,圆括号个人SELECT语句并把ORDER BYLIMIT最后一个之后。

继文档的建议,您的查询应该是:

(
    SELECT animation_id, animation_name, animation_group 
    FROM animations 
    WHERE animation_id = '45' 
) 
UNION ALL 
(
    SELECT animation_id, animation_name, animation_group 
    FROM animations 
    WHERE animation_id <> '45' and active = true 
) 
ORDER BY animation_group, animation_name 

更多,你的查询选择要么animation_id = 45 OR active = true,因此可以写成记录:

SELECT animation_id, animation_name, animation_group 
FROM animations 
WHERE animation_id = '45' OR active = true 
ORDER BY animation_group, animation_name