【问题标题】:MySQL - ORDER BY one column if duplicate or reference doesn't exist in anotherMySQL - 如果另一列中不存在重复或引用,则按一列排序
【发布时间】:2014-11-25 17:31:59
【问题描述】:

我有一个(简化的)表格,如下所示:

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

如您所见,Nancy 和 Steven 已婚(配偶列包含配偶的 ID,如果有)并同居。南希的妹妹安妮也和他们住在一起(不便评论)。

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

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

所以有四种情况:

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

布坎南,史蒂文

达沃里奥,安德鲁

多兹沃思,安妮

富勒,南希

莱弗林,珍妮特

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

布坎南,史蒂文
多兹沃思,安妮
富勒,南希

达沃里奥,安德鲁

莱弗林,珍妮特

按配偶分组 当到达一对夫妇中的第一个人时,都会打印两者:

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

多兹沃思,安妮

达沃里奥,安德鲁

莱弗林,珍妮特

按地址分组配偶 结合以上,配偶优先(所以南希出现在安妮之前,因为她是史蒂夫的配偶)。

布坎南,史蒂文
富勒,南希
多兹沃思,安妮

达沃里奥,安德鲁

莱弗林,珍妮特

如果可能的话,我真的希望它们分组,而不仅仅是一个接一个地排序。如上所示,我想要未分组的人之间的空间,并且分组的人之间没有空间。 这可能只使用 MySQL,还是我也必须使用 PHP?

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

【问题讨论】:

  • 所以你想通过它们被分组来排序,并且在它们没有被分组时返回一个空行?空间有什么好处,你为什么要那样(似乎是一个毫无意义的要求)
  • 对不起,我有点不清楚。我想要打印纸上的空间,而不是 db-result。
  • 那为什么还要问你是否可以在 MySQL 中完成这一切呢? MySQL 将用于获取数据库结果。如果您想以不同的方式打印出来,请在应用层执行此操作
  • 是的,但是应用层应该如何知道哪些是分组的呢?他们只是出现在一个长长的列表中。我不知何故需要知道哪些分组来添加空格。
  • 到目前为止您有什么疑问?你想要什么顺序?

标签: mysql


【解决方案1】:

在这个查询中,我将强制转换语句放在选择部分中,以便您可以看到数据是如何布局的。如果需要,您可以将它们迁移到 ORDER BY,并且只提取名字和姓氏。

案例:按地址和配偶排序

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;

案例:按地址排序

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;

案例:配偶订购

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;

案例:无序

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

Fiddle Demo

注意:如果您将选择与排序保持原样,那么您可以轻松地在应用层中添加空格...例如,如果它拉出 1,那么这意味着该命令对于配偶、地址等都是正确的。如果它是 0 那么它是假的。所以你可以检查值,如果它是 0 开始添加空格

编辑:

在 MySQL 中无法按姓名升序进行排序,但用另一个姓名(配偶或相同地址)覆盖它。您可以使用 CASE 语句检查 php 是否有配偶并在那里更改排序。

【讨论】:

  • 我查看了演示,排序似乎不是我想要的方式。 Nancy 应该在 Steven 之后(他的姓以小写字母开头)。珍妮特和安德鲁也是如此。
  • @Punchlinern 这是一个简单的修复一秒更新小提琴和答案
  • @Punchlinern 你觉得这一切都有意义吗?
  • 太棒了!我试图弄清楚它是如何工作的。我不确定CASE 有什么帮助,或者ORDER BY 12 等如何工作。
猜你喜欢
  • 2022-07-05
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 2020-01-01
  • 2018-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多