MySQL - 如果在另一列中不存在重复或引用,则ORDER BY一列

时间:2014-11-25 17:32:00

标签: mysql

我有一张表(简化)看起来像这样:

+----+--------------+-----------+----------------+----------------+--------+---------+
| ID | First name   | Last name | Street Address | Postal Address | Country | Spouse |
+----+--------------+-----------+----------------+----------------+---------+--------+
| 1  | Nancy        | Fuller    | Street 1       | City 1         | USA     | 4      |
| 2  | Andrew       | Davolio   | Way 2          | Town 2         | USA     | 0      |
| 3  | Janet        | Leverling | Blvd 3         | Village 3      | USA     | 0      |
| 4  | Steven       | Buchanan  | Street 1       | City 1         | USA     | 1      |
| 5  | Anne         | Dodsworth | Street 1       | City 1         | USA     | 0      |
+----+--------------+-----------+----------------+----------------+---------+--------+

如您所见,南希和史蒂文已婚(配偶栏中包含配偶的身份证,如果有的话)并且共同生活。安妮,南希的妹妹,也和他们住在一起(不要轻易评论这些不便)。

现在我要打印这个数据库。我想按姓氏订购,但在打印页面上我有两个选择:

  • 按地址分组
  • 按配偶分组

所以有四种情况:

没有分组
它们只是按姓氏排序:

布坎南,史蒂文

Davolio,Andrew

Dodsworth,Anne

富勒,南希

Leverling,Janet

按地址分组 当到达具有相同地址的多个人的第一个人时,所有人都被打印出来(仍然按照组中的姓氏排序):

布坎南,史蒂文
Dodsworth,Anne
富勒,南希

Davolio,Andrew

Leverling,Janet

由配偶分组 当一对夫妇中的第一个人到达时,两个都被打印出来:

布坎南,史蒂文
富勒,南希

Dodsworth,Anne

Davolio,Andrew

Leverling,Janet

按地址配偶分组 结合上述情况,配偶被优先考虑(因此南希出现在安妮面前,因为她是史蒂夫的配偶)。

布坎南,史蒂文
富勒,南希
Dodsworth,Anne

Davolio,Andrew

Leverling,Janet

我真的希望他们分组,如果可能的话,不只是在彼此之后订购。如上所示,我想要不分组的人之间的空间,并且在分组的人之间没有空间。 这可能只使用MySQL,还是我必须使用PHP?

(我使用PHP 5.5.16和MySQL 5.5.39,PDO对象)

1 个答案:

答案 0 :(得分:2)

在此查询中,我将cast语句放在select部分中,以便您可以看到数据是如何布局的。如果需要,可以将它们迁移到ORDER BY,并且只取出firstname,lastname。

CASE:按地址和配偶排序

SELECT DISTINCT 
    CASE WHEN p1.id IS NOT NULL THEN 1 ELSE 0 END, 
    CASE WHEN p2.id IS NOT NULL THEN 1 ELSE 0 END,
    CONCAT(p.lastname, ', ', p.firstname)
FROM people p
LEFT JOIN people p1 ON p1.spouse = p.id
LEFT JOIN people p2 ON p2.streetaddress = p.streetaddress 
                   AND p.postaladdress = p2.postaladdress 
                   AND p2.id <> p.id
ORDER BY 1 DESC, 2 DESC, 3 ASC;

CASE:按地址排序

SELECT DISTINCT 
    CASE WHEN p2.id IS NOT NULL THEN 1 ELSE 0 END, 
    CONCAT(p.lastname, ', ', p.firstname)
FROM people p
LEFT JOIN people p2 
    ON p2.streetaddress = p.streetaddress 
   AND p.postaladdress = p2.postaladdress 
   AND p2.id <> p.id
ORDER BY 1 DESC, 2 ASC;

CASE:由配偶

订购
SELECT DISTINCT 
    CASE WHEN p1.id IS NOT NULL THEN 1 ELSE 0 END, 
    CONCAT(p.lastname, ', ', p.firstname)
FROM people p
LEFT JOIN people p1 ON p1.spouse = p.id
ORDER BY 1 DESC, 2 ASC;

CASE:无需订购

SELECT
    CONCAT(p.lastname, ', ', p.firstname)
FROM people p;

<强> Fiddle Demo

注意:如果您按顺序保留选择,那么您可以轻松地在应用程序层中添加空格...例如,如果它拉出1然后这意味着订单对于配偶,地址等是真的。如果它是0然后它是假的。所以你可以检查这个值,如果它是0,则开始添加空格

编辑:

按名称升序执行订单,但在MySQL中无法用另一个配偶或相同地址的名称覆盖它。您可以使用CASE语句检查php是否有配偶,并更改其中的顺序。