使用DISTINCT和LEFT JOIN对基于created_at日期的消息列表进行排序

时间:2018-02-27 19:51:50

标签: php sql sorting left-join distinct

我目前有一个从特定用户发送给其他用户的消息列表。此列表包含有关收件人ID的信息,以及邮件发送的时间(以及其他列)。

我需要根据邮件发送的时间对此列表进行排序,同时还要使收件人保持邮件的唯一性。此外,我需要从用户数据库中LEFT JOIN信息,该数据库包含收件人名字和姓氏的列。

为此,我使用以下SQL查询:

SELECT
DISTINCT ON (uc.to_user_id)
        uc.id,
        uc.to_user_id,
        uc.created_at,
        u.first_name,
        u.last_name
FROM user_communication uc
LEFT JOIN "user" u ON (u.id = uc.to_user_id)
WHERE uc.from_user_id = :user_id

其中user_id是传递给PHP的参数。

但是,此查询不会在发送邮件时对邮件列表进行排序。由于在uc.to_user_id上使用了DISTINCT,因此date_created无法对消息进行排序。

目前,输出如下:

"communications": [
        {
            "id": "1da9f6ea-8b4d-11e6-8698-2bd5d7c3680b",
            "created_at": "2016-10-05 22:43:20",
            "user": {
                "user_id": "a1cc4284-60cd-11e6-a419-e7a2176c4be3",
                "first_name": "Test",
                "last_name": "Account"
            }
        },
        {
            "id": "05d6c44a-1be7-11e8-be13-abe8f9af8d9c",
            "created_at": "2018-02-27 17:52:48",
            "user": {
                "user_id": "c84d2ff0-f537-11e6-b318-f7c577b9597c",
                "first_name": "test",
                "last_name": "test"
            }
        },
        {
            "id": "16cc5d64-1be7-11e8-87dd-7fa156fb7904",
            "created_at": "2018-02-27 17:53:16",
            "user": {
                "user_id": "c8c6ff00-452f-11e6-91e3-cbb55bd856a3",
                "first_name": "test",
                "last_name": "account"
            }
        }
 ]

此列表目前按字母数字式由user_id(即uc.to_user_id)排序。

我想知道什么是更好的查询来处理这个问题。

3 个答案:

答案 0 :(得分:0)

SELECT *
  FROM
(
SELECT DISTINCT ON (uc.to_user_id)
        uc.id,
        uc.to_user_id,
        uc.created_at,
        u.first_name,
        u.last_name
FROM user_communication uc
LEFT JOIN "user" u ON (u.id = uc.to_user_id)
WHERE uc.from_user_id = :user_id)
ORDER BY created_at

答案 1 :(得分:0)

也许您可以为这两个表共享您的模式,但只是将列简化为我们需要看到的内容(即我们只需要一些列,以便我们可以专注于主要问题)。

SELECT
        uc.to_user_id,
        uc.id,
        uc.to_user_id,
        uc.created_at,
        u.first_name,
        u.last_name
FROM user_communication uc
LEFT JOIN "user" u ON (u.id = uc.to_user_id)
WHERE uc.from_user_id = :user_id
GROUP BY uc.to_user_id
ORDER BY uc.to_user_id, uc.created_at

您从上面得到了什么样的结果?我很好奇在这种情况下您想要摆脱DISTINCT的重复行的样子。

使用GROUP BY,您可以根据您的要求对某些属性求和或计算。也许这不会帮助您解决问题,因此您可能希望将其删除。

答案 2 :(得分:0)

要仅为每个收件人获取最新邮件,您可以使用以下行的窗口函数:

SELECT * /* Be better to explicitly list your columns again. */
FROM (
    SELECT uc.id
        , uc.to_user_id
        , uc.created_at
        , u.first_name
        , u.last_name
        , ROW_NUMBER() OVER (PARTITION BY uc.to_user_id ORDER BY uc.created_at DESC) as rn
    FROM user_communication uc
    LEFT JOIN "user" u ON (u.id = uc.to_user_id)
    WHERE uc.from_user_id = :user_id
) s1
WHERE s1.rn = 1

我不确定PHP如何使用窗口函数,但这应该可以让您了解如何解决此问题。