2011-12-30 129 views
13

这里是我的查询mysql命令似乎不工作

(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

回答

20

从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 ... 

那么你会看到的前十个记录,将根据该顺序返回,但不一定会按顺序显示。

UPDATE:

试试这个 -

(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 
+0

对于如何以我想要的方式工作,您有什么想法吗?本质上,我想结合不同的查询,并且每个查询都有各自的排序和起伏,然后相互组合。 – 2011-12-30 23:58:57

+0

所以第一个查询排序,然后第二个排序。如果第一个查询大于30,那么它只会显示第一个查询中的前30个。 – 2011-12-30 23:59:45

+0

Bleh,这是一个艰难的。你是说你不想对整个集合进行正确排序?只需要将一个有序集合追加到另一个集合的末尾,并拿出第一个30? – 2011-12-31 00:03:03

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 
+0

我曾考虑过这个问题,但正如我上面提到的那样,这不是我要找的结果。来自第一个查询的所有结果应始终在第二个查询的结果之前。 – 2011-12-31 00:01:40

+1

我编辑了查询以满足您的需求(添加了一个额外的字段'p') – 2011-12-31 00:07:52

+1

我会给你,但其他人先有正确的解决方案。虽然 – 2011-12-31 00:10:15

0

你应该能够使用UNION ALL删除重复的去除(以及整个结果集排序)。使用该结果集应该按照查询中选择语句的顺序。

+0

所以,只需要用UNION ALL替换UNION? – 2011-12-31 00:14:17

+0

尝试一下,看看它是否有帮助,如果没有,我浪费了不超过20秒的时间:) ..(我没有本地mysql方便测试它,但它应该有所作为) – cairnz 2011-12-31 00:15:18

+0

等待,我不想重复。 – 2011-12-31 00:16:34

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 

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

+0

谢谢!我花了数小时试图弄清楚这一点。 – 2017-03-19 13:44:03