【问题标题】:SQL and/or JPQL Statement to retrieve single record sorted by date descSQL 和/或 JPQL 语句检索按日期降序排序的单个记录
【发布时间】:2019-09-19 13:24:17
【问题描述】:

需要 SQL 和/或 JPQL 语句来检索按日期(降序)排序的给定帐户的最新记录。它应该为所有用户返回一条记录(最新记录),例如如果“用户 a”发送/接收来自“用户 b”、“用户 c”和“用户 d”的多条消息,它将返回每个用户的最新记录(总共 3 条)。

我在 JPQL 的尝试:

SELECT DISTINCT dm FROM DirectMessage dm WHERE (dm.messageFrom.id=1 OR dm.messageTo.id=1)  GROUP BY dm.id, dm.messageFrom.id, dm.messageTo.id ORDER BY dm.date DESC

带有架构的具体示例:

如果我希望返回“用户 a”的最新记录,则返回的正确记录数为 3(在下面为这 3 条记录中的每一条插入语句):

1.INSERT INTO direct_message VALUE(2, 2, 1, 'hello back', now());
2.INSERT INTO direct_message VALUE(4, 3, 1, 'hello back', now());
3.INSERT INTO direct_message VALUE(6, 4, 1, 'hello back', now());

脚本

CREATE TABLE account(
    id bigint UNSIGNED NOT NULL auto_increment,
    username varchar(75) NOT NULL,
    name varchar(70) NOT NULL,
    date datetime NOT NULL,
    CONSTRAINT pkey_account_id PRIMARY KEY(id)
);

INSERT INTO account VALUES (1,'user_a','User A', now());
INSERT INTO account VALUES (2,'user_b','User B', now());
INSERT INTO account VALUES (3,'user_c','User C', now());
INSERT INTO account VALUES (4,'user_d','User D', now());



    CREATE TABLE direct_message(
        id bigint UNSIGNED NOT NULL auto_increment,
        message_from_id bigint UNSIGNED NOT NULL,
        message_to_id bigint UNSIGNED NOT NULL,
        message_text varchar(200) NOT NULL,
        date datetime NOT NULL,
        CONSTRAINT pkey_dm_id PRIMARY KEY(id),
        CONSTRAINT fk_direct_message_to FOREIGN KEY (message_to_id) REFERENCES account(id),
        CONSTRAINT fk_message_from FOREIGN KEY (message_from_id) REFERENCES account(id)
    );

    INSERT INTO direct_message VALUE(1, 1, 2, 'hello', now());
    INSERT INTO direct_message VALUE(2, 2, 1, 'hello back', now());
    INSERT INTO direct_message VALUE(3, 1, 3, 'hello', now());
    INSERT INTO direct_message VALUE(4, 3, 1, 'hello back', now());
    INSERT INTO direct_message VALUE(5, 1, 4, 'hello', now());
    INSERT INTO direct_message VALUE(6, 4, 1, 'hello back', now());
    INSERT INTO direct_message VALUE(7, 2, 4, 'hello', now());
    INSERT INTO direct_message VALUE(8, 4, 2, 'hello back', now());

【问题讨论】:

    标签: mysql sql jpql


    【解决方案1】:

    我想你想要:

    select dm.*
    from direct_message dm
    where @userid in (dm.message_from_id, dm.message_to_id) and
          dm.date = (select max(dm2.date)
                     from direct_message dm2
                     where (dm2.message_from_id, dm2.message_to_id) in ( (dm.message_from_id, dm.message_to_id), (dm.message_to_id, dm.message_from_id) )
                    );
    

    编辑:

    具有完全相同的日期/时间戳的不同消息似乎很奇怪,但您可以使用 id 区分它们:

    select dm.*
    from direct_message dm
    where 1 in (dm.message_from_id, dm.message_to_id) and
          dm.id = (select dm2.id
                   from direct_message dm2
                   where (dm2.message_from_id, dm2.message_to_id) in ( (dm.message_from_id, dm.message_to_id), (dm.message_to_id, dm.message_from_id) )
                   order by dm2.date desc
                   limit 1
                  );
    

    【讨论】:

    • 返回超过 3 行(包括旧记录)见这里测试here
    • 应该返回 id 1 和 id 2 之间的单条记录(hello back),其他用户也一样
    • @JamieWhite 。 . .与同一个人的不同消息具有重复的日期/时间戳似乎很奇怪。但是您可以使用 id 来区分它们。
    • 初始解决方案是正确的。将 DATE_SUB(NOW(), INTERVAL 1 DAY)) 添加到所有 'hello' 似乎会产生正确的结果。
    猜你喜欢
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    相关资源
    最近更新 更多