如何在mysql UNION子查询中对数据进行排序?

时间:2015-05-12 13:49:25

标签: mysql sql-order-by union

我需要从表中选择所有vip并按rand排序,然后添加按日期排序的其他数据。在第一个子查询中,一切正常,但在第二个顺序中,spa_date DESC 不起作用。我知道UNION子查询中的ORDER BY子句在没有LIMIT的情况下被忽略(但是按照rand()的顺序工作),但我需要限制所有查询(1 + 2),而不是来自子查询

SELECT * FROM
        (
           select *,DATE_FORMAT(spa_date,"%e %M %Y") as spa_date_out 
            from spa join city using (city_id) 

            where spa_vip=1
            order by RAND() 
         )   as A
        UNION
        (
           select *,DATE_FORMAT(spa_date,"%e %M %Y") as spa_date_out 
            from spa join city using (city_id) 

            where spa_vip=0
            order by spa_date DESC )

        limit 10,10

问题:
我需要选择所有spa_id,其中spa_vip = 1并按RAND()排序,然后我需要选择所有spa_id,其中spa_vip = 0并按spa_date排序,联合这2个子查询并选择限制为0,10的数据等等用于页面视图

1 个答案:

答案 0 :(得分:3)

我不确定是否有任何问题可以解答您的问题,因为我没有看到任何问题。

如果您问的问题“为什么我会观察到这种行为?”,请参阅下面的答案。

如果您要问,“我需要对我的陈述做出哪些更改,以便MySQL按特定顺序返回行?”,请参阅下面的答案。

如果你问,“我需要运行的确切陈述是什么?”,我们真的只是在猜测,因为不清楚你想要的行返回的顺序是什么,有没有明确的规范或描述,没有示例数据或示例输出,或者应首先返回哪些行的基本原理。

MySQL可以按其选择的任何顺序自由返回行,因为最外层查询中没有ORDER BY子句。 (MySQL实际上可以忽略内联视图查询中的ORDER BY子句,并且符合ANSI SQL标准的规范。)

为了保证查询返回的行将按特定顺序返回,请在 ORDER BY之前在外部查询上添加 LIMIT 子句条款。

请注意, UNION 设置运算符要求MySQL检查组合集中的“重复”行,并删除所有重复的行。

如果您无需执行该操作,则可以使用 UNION ALL 设置运算符代替 UNION

在MySQL中,也可以省略SELECT * FROM语句的开头。

我可以提供“试试这个”示例SQL,但不知道你实际想要返回的行的顺序,我们只是猜测。)

这是我对查询的猜测,该查询返回您期望的“顺序”中的行。

我将使用UNION ALL设置运算符显示此内容:

    ( 
      SELECT *,DATE_FORMAT(spa_date,"%e %M %Y") as spa_date_out 
        FROM spa
        JOIN city USING (city_id) 
       WHERE spa_vip=1
    )
    UNION ALL
    ( 
      SELECT *,DATE_FORMAT(spa_date,"%e %M %Y") as spa_date_out 
        FROM spa
        JOIN city USING (city_id) 
       WHERE spa_vip=0
    )
    ORDER
       BY spa_vip DESC
        , IF(spa_vip=1,RAND(),0)
        , IF(spa_vip=0,spa_date,NULL) DESC
    LIMIT 10,10

让我们解开一点点。有两个返回行的查询,UNION ALL集合运算符将这两个集合组合成一个集合。 (如果您使用UNION集合运算符删除重复项的目的,则可以通过将此查询中的UNION ALL替换为UNION来恢复该行为。)

ORDER BY子句 spa_vip 中的第一个表达式首先从第一个集合中获取行...我们保证从第一个查询返回的所有行spa_vip的值为1,第二个查询的所有行的值都为0.

第二个表达式为第一个查询中的行返回RAND(),为第二个查询中的行返回常量。

第三个表达式为第一个查询中的所有行返回一个常量,为第二个查询中的行返回一个值。

如果这是您期望返回的结果,那么同样的结果也可以通过如下语句返回:

   SELECT *,DATE_FORMAT(spa_date,"%e %M %Y") as spa_date_out 
     FROM spa
     JOIN city USING (city_id) 
    WHERE spa_vip IN (0,1)
    ORDER
       BY spa_vip DESC
        , IF(spa_vip=1,RAND(),0)
        , IF(spa_vip=0,spa_date,NULL) DESC
    LIMIT 10,10