按升序将数据插入空单元格

时间:2014-12-11 21:14:17

标签: sql postgresql left-join window-functions generate-series

我有一个Postgres表,其结构如下:

CREATE TABLE tb1 (
id integer,
name text,
date date,
time time without tz
);

CREATE TABLE tb2 (
id integer,
name text,
date date
);

我需要生成第3个表tb3,其中列time_now的增量步长为10分钟。如果tb1.timetb3.time_now不同,则会填写b2.name。如果tb1.time等于(或靠近time_now),则会将其插入{{1} }}。
例如:

TB1

tb3

TB2

1, xxxx, 2014-10-01, 08:20:00
2, yyyy, 2014-10-01, 08:40:00

第3个表应该如下:

1, zzzz, 2014-10-01
2, vvvv, 2014-10-01
3, eeee, 2014-10-01

如何实现这一目标?

1 个答案:

答案 0 :(得分:0)

SELECT t.id, t.time::text, COALESCE(t.name, t2.name) AS name
FROM  (
   SELECT g.id, g.time, t1.name
        , CASE WHEN t1.name IS NULL THEN
            row_number() OVER (PARTITION BY t1.name ORDER BY g.id)
          END AS rn
   FROM  (
      SELECT g AS id, '08:00'::time + '10 min'::interval * (g-1) AS time
      FROM   generate_series (1,6) g
      ) g
   LEFT JOIN tb1 t1 USING (time)
   ) t
LEFT   JOIN tb2 t2 ON t2.id = t.rn
ORDER  BY t.id;
  1. 首先使用generate_series()构建所需时间的表格。在我的例子中从8:00到8:50。

  2. 加入time上的tb1。使用row_number()(rn)将升序编号附加到空插槽。

  3. 按升序将tb2加入剩余的空位。

  4. 使用COALESCE从tb1tb2中选择姓名。

  5. 警惕1分之一的错误。

    SQL Fiddle.

    除此之外:我会使用这些列名的 none idname不具有描述性 - 从不使用它们,更具体。 datetime是基本类型名称。