MySQL ORDER BY Column = value AND distinct?

时间:2014-06-24 14:13:43

标签: mysql sql asp-classic field sql-order-by

我现在已经白发了......

我有一张这样的桌子。

ID - Place - Person
1 - London - Anna
2 - Stockholm - Johan
3 - Gothenburg - Anna
4 - London - Nils

我希望得到包含所有不同人物的结果,但我想选择要订购的地方。

例如。我希望得到一份伦敦订购的清单,其余的将跟随,但在PERSON上有所不同。

Output like this:
ID - Place - Person
1 - London - Anna
4 - London - Nils
2 - Stockholm - Johan

试过这个:

SELECT ID, Person
FROM users        
ORDER BY FIELD(Place,'London'), Person ASC "

但它给了我:

ID - Place - Person
1 - London - Anna
4 - London - Nils
3 - Gothenburg - Anna
2 - Stockholm - Johan

而且我真的不希望安娜或任何人在结果中多出一次。

3 个答案:

答案 0 :(得分:1)

这是获取指定输出的一种方法,但这使用了MySQL特定的行为,这是不能保证的:

SELECT q.ID
     , q.Place
     , q.Person
  FROM ( SELECT IF(p.Person<=>@prev_person,0,1) AS r
              , @prev_person := p.Person AS person
              , p.Place
              , p.ID
           FROM users p
          CROSS
           JOIN (SELECT @prev_person := NULL) i  
          ORDER BY p.Person, !(p.Place<=>'London'), p.ID
       ) q
 WHERE q.r = 1
ORDER BY !(q.Place<=>'London'), q.Person

此查询使用内联视图按Person按特定顺序返回所有行,以便所有'Anna'行在一起,然后是所有'Johan'行等。行的集合为每个人先按Place='London',然后按ID排序。

“技巧”是使用MySQL用户变量将当前行的值与前一行的值进行比较。在这个例子中,我们检查当前行上的'Person'是否与前一行的'Person'相同。根据该检查,如果这是我们为一个人处理的“第一”行,则返回1,否则返回0。

最外层查询处理内联视图中的行,并排除除每个Person的“第一”行之外的所有行(我们从内联视图返回的0或1)。

(这不是获取结果集的唯一方法。但这是模拟其他RDBMS中可用的分析函数的一种方法。)


为了比较,在数据库其他而不是MySQL中,我们可以使用这样的SQL:

SELECT ROW_NUMBER() OVER (PARTITION BY t.Person ORDER BY 
         CASE WHEN t.Place='London' THEN 0 ELSE 1 END, t.ID) AS rn
      , t.ID
      , t.Place
      , t.Person
   FROM users t
  WHERE rn=1
  ORDER BY CASE WHEN t.Place='London' THEN 0 ELSE 1 END, t.Person

<强>跟进

在答案的开头,我提到了无法保证的MySQL行为。我指的是在SQL语句中使用MySQL用户定义的变量。

摘自MySQL 5.5参考手册http://dev.mysql.com/doc/refman/5.5/en/user-variables.html

“作为一般规则,除了在SET语句中,您不应该为用户变量赋值并在同一语句中读取值。”

“对于其他语句,例如SELECT,您可能会得到您期望的结果,但这不能保证。”

“涉及用户变量的表达式的评估顺序未定义。”

答案 1 :(得分:0)

您想使用group by代替distinct

SELECT ID, Person
FROM users   
GROUP BY ID, Person     
ORDER BY MAX(FIELD(Place, 'London')), Person ASC;

GROUP BYSELECT DISTINCT的作用相同。但是,您可以在HAVINGORDER BY等条款中提及其他字段。

答案 2 :(得分:0)

试试这个:

SELECT ID, Place, Person
FROM users
GROUP BY Person
ORDER BY FIELD(Place,'London') DESC, Person ASC;