'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
Output
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
How do I find the first record WHERE tracker_id IN ('15', '11', '12')
in a single query?
I can find the first record by separately querying for each tracker_id
:
SELECT *
FROM my_table
WHERE tracker_id = '15'
ORDER BY timestamp
LIMIT 1;
Solution 1:[1]
In Postgres this can be done using the DISTINCT ON ()
clause:
select distinct on (tracker_id) *
from the_table
where tracker_id in (11,12,15)
order by tracker_id, "timestamp" desc;
Solution 2:[2]
I have named your timestampl column col1 because I do nto recommend to name your columns with keywords.
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);
Solution 3:[3]
You can use first_value
with the nested select
query:
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')
)
I'm assuming timestamp
is unique, like you said in the comment. You can always replace the joining column with a primary key, like id
.
Solution 4:[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;
Solution 5:[5]
If you want the first row that matches each of your IN
values, you can use a window function:
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
This will return the first row that matches for each of your IN
values, ordering by timestamp
.
Solution 6:[6]
Find this Query:
You can uncomment where clause if you want to run query for selected tracker_id
;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
Solution 7:[7]
select distinct on (tracker_id) *
from table
where tracker_id in (11,12,15)
order by tracker_id, "timestamp" asc;
i use distinct on when use postgres for this case
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | VBoka |
Solution 3 | |
Solution 4 | Khalid |
Solution 5 | ravioli |
Solution 6 | |
Solution 7 | khoa junior |