我现在已经白发了......
我有一张这样的桌子。
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
而且我真的不希望安娜或任何人在结果中多出一次。
答案 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 BY
与SELECT DISTINCT
的作用相同。但是,您可以在HAVING
和ORDER BY
等条款中提及其他字段。
答案 2 :(得分:0)
试试这个:
SELECT ID, Place, Person
FROM users
GROUP BY Person
ORDER BY FIELD(Place,'London') DESC, Person ASC;