Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL按组删除重复项_Sql_Postgresql_Sql Order By_Distinct_Greatest N Per Group - Fatal编程技术网

PostgreSQL按组删除重复项

PostgreSQL按组删除重复项,sql,postgresql,sql-order-by,distinct,greatest-n-per-group,Sql,Postgresql,Sql Order By,Distinct,Greatest N Per Group,我想打印一个人的最后一条消息,但每人只打印他最近的消息。我使用PostgreSQL 10 +-----------+----------+--------------+ | name | body | created_at | +-----------+----------+--------------+ | Maria | Test3 | 2017-07-07 | | Paul | Test5 | 2017-06-01 | +----

我想打印一个人的最后一条消息,但每人只打印他最近的消息。我使用PostgreSQL 10

+-----------+----------+--------------+
| name      |   body   |  created_at  |
+-----------+----------+--------------+
| Maria     | Test3    |  2017-07-07  |
| Paul      | Test5    |  2017-06-01  |
+-----------+----------+--------------+
我已经在下面的SQL查询中尝试过了,这给了我确切的答案,但不幸的是,使用它的人数增加了一倍

从消息中选择*
其中receive='t'
按名称分组
最大订单(创建时)描述
我试图用一个不同的名称删除重复项,但不幸的是,我收到以下错误消息:

从消息中选择DISTINCT ON(名称)*
其中receive='t'
按名称分组
最大订单(创建时)描述

你知道我如何解决这个问题吗?

你可以在上使用
DISTINCT,如下所示:

SELECT DISTINCT ON (name) * 
FROM messages 
WHERE receive = 't'
ORDER BY name, created_at DESC
即:

  • 不需要
    分组依据
    子句

  • 在(…)
中列出的列必须首先出现在
ORDER BY
子句中

  • 。。。然后是应用于断开组的列(此处,即在处创建的

  • 请注意,
    distinct on
    查询的结果总是按子句中的列排序(因为这种排序用于标识应保留哪些行)

    如果希望对排序顺序进行更多控制,则可以改用窗口函数:

    SELECT *
    FROM (
        SELECT m.*, ROW_NUMBER() OVER(PARTITION BY name ORDER BY created_at DESC) rn
        FROM messages m
        WHERE receive = 't'
    ) t
    WHERE rn = 1
    ORDER BY created_at DESC
    

    上使用不同的,但使用右侧的按排序:

    SELECT DISTINCT ON (name) m.*
    FROM messages m
    WHERE receive = 't'
    ORDER BY name, created_at DESC;
    
    一般情况下,您不会将
    上的DISTINCT ON
    分组依据一起使用。它与订购人一起使用。它的工作方式是基于
    orderby
    子句为每个
    name
    选择第一行

    你不应该把你正在做的事情看作是聚合。您希望根据在
    创建的
    进行筛选。在许多数据库中,可以使用相关子查询来表示:

    select m.*
    from messages m
    where m.created_at = (select max(m2.created_at)
                          from messages m2
                          where m2.name = m.name and m2.receive = 't'
                         ) and
          m.receive = 't';   -- this condition is probably not needed
    
    上面的查询查找满足以下条件的消息:

    • 接收是't'
    • 不存在另一条
      • 具有与接收相同的值
      • 同名
      • 而且是新的

    假设相同的名称不能同时发送两条消息,这就足够了。另一点需要指出的是,如果值中存在一些白色字符,则名称可能看起来相似,但可能不同。因此,如果您在结果中看到两条记录具有相同的名称,但在上面的查询中创建的位置不同,然后,很可能是白人角色在捉弄你。

    但随后会按名称排序。当我尝试使用子查询执行此操作时,最新的条目将丢失。为什么会这样?
    SELECT DISTINCT ON (name) m.*
    FROM messages m
    WHERE receive = 't'
    ORDER BY name, created_at DESC;
    
    select m.*
    from messages m
    where m.created_at = (select max(m2.created_at)
                          from messages m2
                          where m2.name = m.name and m2.receive = 't'
                         ) and
          m.receive = 't';   -- this condition is probably not needed
    
    SELECT * 
    FROM messages 
    WHERE receive = 't' and not exists (
        select 1
        from messages m
        where m.receive = message.receive and messages.name = m.name and m.created_at > messages.created_at
    )
    ORDER BY created_at DESC