【问题标题】:Find first record of multiple values in single query在单个查询中查找多个值的第一条记录
【发布时间】:2020-06-14 10:50:18
【问题描述】:

表格

            timestamp             | tracker_id | position 
----------------------------------+------------+----------
 2020-02-01 21:53:45.571429+05:30 |         15 |        1
 2020-02-01 21:53:45.857143+05:30 |         11 |        1
 2020-02-01 21:53:46.428571+05:30 |         15 |        1
 2020-02-01 21:53:46.714286+05:30 |         11 |        2
 2020-02-01 21:53:54.714288+05:30 |         15 |        2
 2020-02-01 21:53:55+05:30        |         12 |        1
 2020-02-01 21:53:55.285714+05:30 |         11 |        1
 2020-02-01 21:53:55.571429+05:30 |         15 |        3
 2020-02-01 21:53:55.857143+05:30 |         13 |        1
 2020-02-01 21:53:56.428571+05:30 |         11 |        1
 2020-02-01 21:53:56.714286+05:30 |         15 |        1
 2020-02-01 21:53:57+05:30        |         13 |        2
 2020-02-01 21:53:58.142857+05:30 |         12 |        2
 2020-02-01 21:53:58.428571+05:30 |         20 |        1

输出

           timestamp             | tracker_id | position 
----------------------------------+------------+----------
2020-02-01 21:53:45.571429+05:30 |         15 |        1
2020-02-01 21:53:45.857143+05:30 |         11 |        1
2020-02-01 21:53:55+05:30        |         12 |        1

如何在单个查询中找到第一条记录WHERE tracker_id IN ('15', '11', '12')

我可以通过分别查询每个tracker_id找到第一条记录:

SELECT *
FROM my_table
WHERE tracker_id = '15'
ORDER BY timestamp
LIMIT 1;

【问题讨论】:

  • 该表中是否有主键?
  • @Andronicus 没有主键约束,但 timestamp 将是唯一的
  • @saintlyzero 检查我的查询,优化并在下面完美运行。

标签: sql database postgresql distinct greatest-n-per-group


【解决方案1】:

在 Postgres 中,这可以使用 DISTINCT ON () 子句来完成:

select distinct on (tracker_id) *
from the_table
where tracker_id in (11,12,15)
order by tracker_id, "timestamp" desc;

Online example

【讨论】:

    【解决方案2】:

    我已将您的时间戳列命名为 col1,因为我不建议您使用关键字来命名您的列。

    select * from mytable m
    where m.col1 = (select min(col1)
                  from mytable m1
                  where m.tracker_id = m1.tracker_id
                  group by tracker_id)
    and m.tracker_id in (11,15,12);
    

    Here is a small demo

    【讨论】:

      【解决方案3】:

      您可以将first_value 与嵌套的select 查询一起使用:

      select mt.*
      from my_table mt
      where mt.timestamp in (
          select first_value(imt.timestamp) over (partition by imt.tracker_id order by imt.timestamp)
          from my_table imt
          where imt.tracker_id in ('11', '12', '15')
      )
      

      我假设timestamp 是独一无二的,就像你在评论中所说的那样。您始终可以使用主键替换连接列,例如 id

      【讨论】:

        【解决方案4】:
        select distinct on (tracker_id) *
        from the_table
        where tracker_id in ( select distinct tracker_id from the_table)
        order by tracker_id, "timestamp" desc;
        

        【讨论】:

          【解决方案5】:

          如果您希望第一行与您的每个 IN 值匹配,您可以使用窗口函数:

          SELECT src.timestamp, src.tracker_id, src.position
          FROM (
            SELECT 
              t.timestamp, t.tracker_id, t.position, 
              ROW_NUMBER() OVER(PARTITION BY tracker_id ORDER BY timestamp DESC) myrownum
            FROM mytable t
            WHERE tracker_id IN ('15', '11', '12')
          ) src
          WHERE myrownum = 1 -- Get first row for each "tracker_id" grouping
          

          这将返回与您的每个IN 值匹配的第一行,按timestamp 排序。

          【讨论】:

            【解决方案6】:

            找到这个查询:

            如果您想对选定的 tracker_id 运行查询,您可以取消注释 where 子句

               ;WITH CTE AS
               (
                  SELECT ROW_NUMBER() OVER (PARTITION BY tracker_id ORDER BY timestamp) 
                  duplicates, * FROM my_table -- WHERE tracker_id IN (15,11,12)
               )
               SELECT timestamp, tracker_id, position FROM CTE WHERE duplicates = 1
            

            【讨论】:

            • 在标记为好意之前运行查询并查看它是测试查询的结果
            • 这可能是因为ERROR: syntax error at or near "[" (并且Postgres 需要在语句末尾而不是开头的语句终止字符;
            • 嘿@a_horse_with_no_name 只是拼写错误,请重新运行它,它适用于所有tracker id,如果您想要选择tracker_id,您可以在where 子句中传递它。
            • 这仍然无效(标准 SQL)并且不会在 Postgres 上运行
            • 它在 postgress 上也能完美运行,方括号在 postgress 时给出错误,所以我删除了方括号
            猜你喜欢
            • 2021-04-09
            • 2021-04-11
            • 1970-01-01
            • 2013-12-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-30
            • 2019-07-22
            相关资源
            最近更新 更多