需要一个 SQL 查询,它将与另一个 table 左联接,后者又会 return 基于时间的最新值,分组到一行中

Need an SQL query that will left join with another table, which will in turn return the latest values based on time, grouped into a single row

我需要有关 SELECT SQL 查询的帮助,该查询将在 id 列上与另一个 table 左连接,后者又将 return 最新值基于时间,分组为一行?

基本上,加入两个 table 的方式使得用户 table 中存在于 time_series table、return 中的每条记录基于时间的最新值分组为一行。

用户table:

id  |  name
----+--------
 1  | "Joe" 
 2  | "Ron" 

time_series table:

time| id  |  a  |  b  | c  | d
----+-----+-----+-----+----+----
 1  |  1  |  a1 |     |    |
 2  |  1  |     |  b1 |    |
 3  |  1  |     |     | c0 |
 4  |  1  |  a3 |     | c3 |
 5  |  1  |  a0 |     |    |
 6  |  2  |  a3 |     | c3 | d1
 7  |  2  |  a2 |     |    | d3

结果应如下所示:

id  |  a  |  b  | c  | d  | name
----+-----+-----+----+----+------
 1  |  a0 |  b1 | c3 |    | "Joe"
 2  |  a2 |     |    | d3 | "Ron"

一个选项使用几个子查询:

select u.*,
    (select ts.a from time_series ts where ts.id = u.id and ts.a is not null order by ts.time desc limit 1) a,
    (select ts.b from time_series ts where ts.id = u.id and ts.b is not null order by ts.time desc limit 1) b,
    (select ts.c from time_series ts where ts.id = u.id and ts.c is not null order by ts.time desc limit 1) c,
    (select ts.d from time_series ts where ts.id = u.id and ts.d is not null order by ts.time desc limit 1) d
from users u

另一种解决方案是对每列row_number()的行进行排序,优先考虑非null值,然后进行条件聚合:

select u.id,
    max(case when ts.rn_a = 1 then ts.a end) a,
    max(case when ts.rn_b = 1 then ts.b end) a,
    max(case when ts.rn_c = 1 then ts.c end) a,
    max(case when ts.rn_d = 1 then ts.d end) d
from users u
inner join (
    select ts.*,
        row_number() over(order by (case when a is null then 1 else 0 end), time desc) rn_a,
        row_number() over(order by (case when b is null then 1 else 0 end), time desc) rn_b,
        row_number() over(order by (case when c is null then 1 else 0 end), time desc) rn_c,
        row_number() over(order by (case when d is null then 1 else 0 end), time desc) rn_d
    from time_series ts
) ts on ts.id = u.id
group by u.id

我认为您要查找的函数是 coalesce

SELECT u.id
    , coalesce(a)
    , coalesce(b)
    , coalesce(c)
    , coalesce(d)
    , name
FROM users u 
LEFT JOIN time_series ts
    ON u.id = ts.id
GROUP BY 1, 6
ORDER BY ts.time DESC;