您可以(MySQL)通过可选值在不同表中进行排序吗?

时间:2018-12-21 15:14:55

标签: php mysql sorting pdo

因此,我有一个相当基本的基于PHP的网站,该网站的某些数据使用MySQL。

我目前需要以一种依赖于其他表中可选字段的方式对MySQL结果行进行排序,我想知道这是否“轻松”可实现。

这是数据库的外观(排序):

主表称为“主”

    | id |  timestamp |  starttime |
    |  1 | 2010-06-10 | 2010-08-15 |
    |  2 | 2011-01-15 | 2011-03-12 |
    |  3 | 2011-01-27 | 0000-00-00 |

附表称为“附件”

    | aid |  timestamp | id |
    |   1 | 2012-09-04 |  3 |
    |   2 | 2017-04-01 |  3 |

版本表称为“修订”

    | rid |  timestamp | id |
    |   1 | 2014-10-10 |  1 |
    |   2 | 2018-12-25 |  2 |

Main表基本上是必需的,附件和修订对于我要提供的有序列表并不重要。

现在,我希望能够按“上次更改日期”对它进行排序,这是一个问题,因为可以通过以下方式对4个值进行排序:

  1. Main.starttime(根据某些用户操作进行更新)
  2. Attachments.timestamp(用户可以随时添加附件)
  3. Revisions.timestamp(用户可以编辑其Main行,将增量作为新行写入到Revisions中)

OR(以上字段均不存在或为零)

  1. Main.timestamp(这是使用NOW()创建行的默认DateTime)

我尝试在ORDER BY子句中使用GREATEST(),并且有效,但仅适用于Main.timestamp和Main.starttime-不适用于我需要考虑的其他两个值。

这是我当前的SQL命令:

SELECT Main.*, User.lastname, User.surname, User.title
FROM Main, User
WHERE User.uid = Main.uid AND Main.state != 0
ORDER BY $orderby LIMIT :limit OFFSET :offset

我的$ orderby变量是通过PHP处理的,因此已经过了清理,但基本上可以是这样的:

$orderby = "Main.timestamp DESC";

或使用GREATEST():

$orderby = "GREATEST(Main.timestamp, Main.starttime) DESC";

我面临的主要问题是,并非“主要”的每一行在“附件”或“修订”中都有对应的行,而有些行有多个。

上面的示例应排序为

2 > 3 > 1

如果排序有效。

希望大家能帮忙!

1 个答案:

答案 0 :(得分:1)

有点棘手,但有效:https://www.db-fiddle.com/f/bUV99RzrxcHkgFyUWUMGEe/0

查询

SELECT
    MAIN.id,
    MAX(MAIN.updated_at) AS 'updated_at'
FROM (
  SELECT
    M.id,
    GREATEST(
          IFNULL(M.`timestamp`, '1970-01-01 00:00:00'),
          IFNULL(M.starttime, '1970-01-01 00:00:00'),
          IFNULL(A.`timestamp`, '1970-01-01 00:00:00'),
          IFNULL(R.`timestamp`, '1970-01-01 00:00:00')
    ) AS 'updated_at'
  FROM
    main M
  LEFT JOIN
    attachment A ON M.id = A.id
  LEFT JOIN
    revision R ON M.id = R.id
) AS MAIN
GROUP BY
    MAIN.id
ORDER BY
    updated_at DESC

说明

我已经使用第一个查询来选择所有主要内容及其相关的附件和修订。然后,对于每个字段,我计算了一个updated_at字段,该字段在许多字段之间取最大值(注:great无效,且值为空,因此IFNULL(date, '1970-01-01 00:00:00)因此假定至少一个日期主时间戳,主开始时间,附件时间戳和修订时间戳之间的值不为null)。

目前,这些行未按主ID分组,因此您在数据库小提琴中看到4行。

我使用了第二个查询来包装最后一个查询,并且我使用了MAX(updated_at) AS 'updated_at'来获取最多的分组查询(您看到名为AS MAIN的包装查询是做GROUP BY MAIN.id,这就是为什么我们使用MAX而不是GREATEST的原因,最后一个使用字段列表而不是分组字段)。

最后,我们通过查询和tada进行订购!

希望有帮助。