基本 MERGE 示例

在此示例中,合并操作涉及两个表:

  • visits_daily 记录每日餐厅流量,并随着每次顾客到访而更新。此表中的数据每 24 小时刷新一次。

  • visits_history 存储顾客到访各个餐厅的历史记录(无限期累计)。

每天晚上,您都会将 visits_daily 的每日到访计数合并到 visits_history。合并操作通过两种方式修改目标表:

  • 更新现有顾客数据。

  • 为首次到访的顾客插入新数据行。

一个 MERGE 语句将这两项操作作为单个 (upsert) 事务来执行。

源表和目标表

源表和目标表 visits_dailyvisits_history 定义如下:

CREATE TABLE public.visits_daily
(
    customer_id int,
    location_name varchar(20),
    visit_time time(0) DEFAULT (now())::timetz(6)
);

CREATE TABLE public.visits_history
(
    customer_id int,
    location_name varchar(20),
    visit_count int
);

visits_history 包含三个顾客行,他们分别到访了 Etoile 和 LaRosa 两家餐厅:

=> SELECT * FROM visits_history ORDER BY customer_id, location_name;
 customer_id | location_name | visit_count
-------------+---------------+-------------
        1001 | Etoile        |           2
        1002 | La Rosa       |           4
        1004 | Etoile        |           1
(3 rows)

到营业结束时,表 visits_daily 包含三行餐厅到访数据:

=> SELECT * FROM visits_daily ORDER BY customer_id, location_name;
 customer_id | location_name | visit_time
-------------+---------------+------------
        1001 | Etoile        | 18:19:29
        1003 | Lux Cafe      | 08:07:00
        1004 | La Rosa       | 11:49:20
(3 rows)

表数据合并

以下 MERGE 语句将 visits_daily 数据合并到 visits_history 中:

  • 对于匹配的顾客,MERGE 会更新出现计数。

  • 对于不匹配的顾客,MERGE 会插入新行。

=> MERGE INTO visits_history h USING visits_daily d
    ON (h.customer_id=d.customer_id AND h.location_name=d.location_name)
    WHEN MATCHED THEN UPDATE SET visit_count = h.visit_count  + 1
    WHEN NOT MATCHED THEN INSERT (customer_id, location_name, visit_count)
    VALUES (d.customer_id, d.location_name, 1);
 OUTPUT
--------
      3
(1 row)

MERGE 返回已更新和插入的行数。在本例中,返回值指定三个更新和插入项:

  • 顾客 1001 第三次到访 Etoile

  • 新顾客 1003 首次到访新餐厅 Lux Cafe

  • 客户 1004 首次到访 La Rosa

如果现在查询表 visits_history,结果集会显示合并(更新和插入)的数据。更新行和新行高亮显示: