在单个查询中查找多个值的第一条记录

Find first record of multiple values in single query

Table

            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;

您可以将 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.

我已将您的时间戳列命名为 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

在 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

查找此查询:

如果你想运行查询选定的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
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;

如果您想要第一行与每个 IN 值相匹配,您可以使用 window 函数:

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

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

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

我在这种情况下使用 postgres 时使用 distinct on