使用union的mysql命令似乎不起作用

时间:2011-12-30 23:52:17

标签: mysql select sql-order-by union

这是我的查询

(SELECT * FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%only three doors%" OR `joke` LIKE "%only three doors%") ORDER BY `ups` DESC,`downs` ASC)
UNION
(SELECT * FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%only%" OR `joke` LIKE "%only%") ORDER BY `ups` DESC,`downs` ASC)
UNION
(SELECT * FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%three%" OR `joke` LIKE "%three%") ORDER BY `ups` DESC,`downs` ASC)
UNION
(SELECT * FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%doors%" OR `joke` LIKE "%doors%") ORDER BY `ups` DESC,`downs` ASC)
 LIMIT 0, 30

由于某些原因,它似乎没有按顺序排序......它只是按照它们在数据库中自然的顺序将结果扔回去。

当我将其剪切为只有一个查询时,它工作正常,但除此之外,它似乎忽略了它。

我也不想按整个结果排序,或者我会放LIMIT 0,30 Order By blah

5 个答案:

答案 0 :(得分:24)

来自MySQL documentation

  

...使用ORDER BY表示各个SELECT语句   没有关于行在最终结果中出现的顺序   因为UNION默认生成一组无序行。

基本上,联盟中ORDER唯一有用的时间是你使用LIMIT

所以,如果您的查询是这样的:

(SELECT * FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%only three doors%" OR `joke` LIKE "%only three doors%") ORDER BY `ups` DESC,`downs` ASC LIMIT 10)
UNION ...

然后,您将看到将根据该订单返回的前十条记录,但它们不一定按顺序显示。

<强>更新

试试这个 -

(SELECT *, 1 as ob FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%only three doors%" OR `joke` LIKE "%only three doors%") )
UNION
(SELECT *, 2 as ob FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%only%" OR `joke` LIKE "%only%") )
UNION
(SELECT *, 3 as ob FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%three%" OR `joke` LIKE "%three%") )
UNION
(SELECT *, 4 as ob FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%doors%" OR `joke` LIKE "%doors%"))
 ORDER BY `ob`, `ups` DESC,`downs` ASC LIMIT 0, 30

答案 1 :(得分:3)

我得到了解决方案:

SELECT *
FROM (
    (SELECT 1 as SortRank, uid, title, state, zip, region,cantone FROM company WHERE city=".$city." AND region=".$region." AND cantone=".$cantone.")
     UNION
    (SELECT 2 as SortRank, uid, title, state, zip, region,cantone FROM company WHERE region=".$region." AND cantone=".$cantone.")
    union all
    (SELECT 3 as SortRank, uid, title, state, zip, region,cantone FROM company WHERE cantone=".$cantone.")
) As u
GROUP BY uid 
ORDER BY SortRank,state=2, title ASC
LIMIT 0,10

在上面的查询中,我想要结果,例如。首先显示城市,地区和cantone的所有记录,然后如果城市不可用,则显示所有带有region和cantone的记录,然后显示所有带有cantone of city的记录。 因此,删除我使用GROUP BY子句的重复记录,它将根据查询组对所有记录进行排序,然后对所有状态为2的记录进行排序。

答案 2 :(得分:2)

查询的作用是分别对每个子查询进行排序并统一所有子查询。无法保证订购结果。

您需要做的是按顺序订购统一查询:

Select * from (
  (SELECT *, 1 as `p` FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%only three doors%" OR `joke` LIKE "%only three doors%"))
  UNION
  (SELECT *, 2 as `p` FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%only%" OR `joke` LIKE "%only%"))
  UNION
   (SELECT *, 3 as `p` FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%three%" OR `joke` LIKE  "%three%"))
  UNION
  (SELECT *, 4 as `p` FROM `jokes` WHERE `flags` < 5 AND (`title` LIKE "%doors%" OR `joke` LIKE "%doors%"))
    ) ORDER BY `p` ASC, `ups` DESC,`downs` ASC

答案 3 :(得分:0)

您应该能够使用UNION ALL删除重复删除(以及完整的结果集排序)。使用它,结果集应该是查询中select语句的顺序。

答案 4 :(得分:0)

也许这与问题有点无关,但对于那些想要联合两个或多个查询的不同列:

由于无法使用一个 order by 语句,因为两个查询中的列不相同,您可以考虑添加“假”列以使两个查询中的列数相等,这是我在 HackerRank 上对 excerise 的回答类似于这里提出的问题

WITH sub AS 
(
(SELECT CONCAT(Name , "(" , SUBSTRING(OCCUPATION,1,1) , ")") as first , Name , OCCUPATION , -1 as counts FROM OCCUPATIONS)
UNION ALL
(SELECT CONCAT("There are a total of " , COUNT(OCCUPATION) , " " , LOWER(OCCUPATION) , "s" , ".") as first , "z" as Name , OCCUPATION , COUNT(OCCUPATION) as counts FROM OCCUPATIONS
GROUP BY OCCUPATION)
)

SELECT first FROM sub
ORDER BY Name ASC , counts ASC , OCCUPATION ASC

注意:您应该为假列选择适当的值以使您的行处于正确位置(注意我的查询中的 -1 as counts FROM OCCUPATIONS"z" as Name

我最初误解了 HackerRank 上的问题,因为它不需要我将两个查询结合起来,但无论如何我最终还是学到了一些新东西,希望对您有所帮助 (: