PostgreSQL LATERAL 的工作原理

LATERAL 的工作原理

  1. 外部查询生成一行结果:LATERAL 子查询会对每一行外部查询结果进行评估。
  2. LATERAL 子查询执行:对于每一行,LATERAL 子查询会使用该行的列值来执行自己的查询。
  3. 结果合并:子查询的结果与外部查询的行合并,形成最终的结果集。

以下是一个简单的例子来说明 LATERAL 的工作原理:

示例表和数据

假设我们有一个名为 employees 的表:

CREATE TABLE employees (
    id SERIAL PRIMARY KEY,
    name TEXT,
    tasks JSONB
);

INSERT INTO employees (name, tasks) VALUES
('Alice', '[{"task": "task1"}, {"task": "task2"}]'),
('Bob', '[{"task": "task3"}, {"task": "task4"}]');

使用 LATERAL 的查询示例

我们想要展开每个员工的任务,并显示员工的名字和每个任务的名字。

SELECT
    e.name,
    t.task
FROM
    employees e,
    LATERAL jsonb_array_elements(e.tasks) AS t(task);

查询解释

  1. 外部查询生成每一行结果

    • 第一行:('Alice', '[{"task": "task1"}, {"task": "task2"}]')
    • 第二行:('Bob', '[{"task": "task3"}, {"task": "task4"}]')
  2. LATERAL 子查询执行

    • 对于第一行,jsonb_array_elements('[{"task": "task1"}, {"task": "task2"}]') 展开成两行:
      • {"task": "task1"}
      • {"task": "task2"}
    • 对于第二行,jsonb_array_elements('[{"task": "task3"}, {"task": "task4"}]') 展开成两行:
      • {"task": "task3"}
      • {"task": "task4"}
  3. 结果合并

    • 第一行展开结果合并:
      • ('Alice', 'task1')
      • ('Alice', 'task2')
    • 第二行展开结果合并:
      • ('Bob', 'task3')
      • ('Bob', 'task4')

结果集

 name  | task
-------|-------
 Alice | task1
 Alice | task2
 Bob   | task3
 Bob   | task4

使用 LATERAL 和 WHERE 子句

假设我们只想筛选出特定的任务,可以在 LATERAL 子查询之后使用 WHERE 子句。

例如,筛选出任务为 task1task3 的记录:

SELECT
    e.name,
    t.task
FROM
    employees e,
    LATERAL jsonb_array_elements(e.tasks) AS t(task)
WHERE
    t.task->>'task' IN ('task1', 'task3');

结果集

 name  | task
-------|-------
 Alice | task1
 Bob   | task3

总结

  • LATERAL 的作用:LATERAL 允许子查询访问外部查询的列,且会对外部查询的每一行进行评估。
  • 子查询与外部查询的关系:子查询可以使用外部查询中的列值来生成结果,并将其合并到最终的结果集中。
  • 临时结果集:LATERAL 子查询的结果会与外部查询的每一行合并,从而形成最终的结果集。

通过使用 LATERAL,我们能够在子查询中引用外部查询的列值,并根据这些列值进行进一步的数据处理和筛选。

是的,你可以使用相同的方法来处理具有多个字段的 JSON 数组。假设每个 JSON 对象都有两个字段 `task``priority`,你可以像这样修改查询来处理它:

```sql
SELECT
    e.name,
    t.task,
    t.priority
FROM
    employees e,
    LATERAL (
        SELECT (elem->>'task') AS task,
               (elem->>'priority') AS priority
        FROM jsonb_array_elements(e.tasks) AS elem
    ) AS t
WHERE
    t.task IN ('task1', 'task3');

在这个查询中,jsonb_array_elements(e.tasks) 将每个 JSON 对象展开成一行,并在子查询中使用 ->> 运算符来提取每个对象的 taskpriority 字段。然后,通过别名 t 引用这些字段。

这样,你就可以处理具有多个字段的 JSON 数组了。



在这个查询中,`LATERAL jsonb_array_elements(e.tasks) AS t(task)` 这一部分是一个 LATERAL JOIN 语句,用于将 JSON 数组 `e.tasks` 中的每个元素展开成一行。让我们来解释一下其中的各个部分:

- `LATERAL`: 这是一个关键字,它告诉数据库引擎在执行查询时按顺序处理 FROM 子句中的表达式,确保对每一行计算一次。在这里,它确保对 `jsonb_array_elements(e.tasks)` 返回的每个元素都进行处理。

- `jsonb_array_elements(e.tasks)`: 这是一个 JSON 函数,它将 JSON 数组 `e.tasks` 中的每个元素作为一个行返回。例如,如果 `e.tasks` 是 `["task1", "task2", "task3"]`,那么这个函数将返回三行,每行一个任务。

- `AS t(task)`: 这部分给返回的行定义了一个别名 `t`,并指定了一个列别名 `task`。在查询的后续部分,你可以使用 `t.task` 来引用 `jsonb_array_elements(e.tasks)` 返回的每一行中的 `task` 列。

所以,整个 LATERAL JOIN 的作用是将 JSON 数组 `e.tasks` 中的每个元素拆分成一行,并将每个元素赋值给名为 `t` 的临时表,该表只有一个名为 `task` 的列。


**可以选择第几个对象**
```sql
SELECT
    e.name,
    t.task,
    t.priority
FROM
    employees e,
    LATERAL (
        SELECT (elem->>'task') AS task,
               (elem->>'priority') AS priority,
							 ROW_NUMBER() OVER () AS rn
        FROM jsonb_array_elements(e.tasks) AS elem
    ) AS t
		left join 
WHERE
t.rn = 1;

相关推荐

  1. ChatGPT工作原理

    2024-06-06 01:18:01       68 阅读
  2. 无人机工作原理

    2024-06-06 01:18:01       17 阅读
  3. 解析:Eureka工作原理

    2024-06-06 01:18:01       54 阅读
  4. FTP服务器工作原理

    2024-06-06 01:18:01       40 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-06 01:18:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-06 01:18:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-06 01:18:01       82 阅读
  4. Python语言-面向对象

    2024-06-06 01:18:01       91 阅读

热门阅读

  1. 【数据库系统概论】触发器

    2024-06-06 01:18:01       31 阅读
  2. 【机器学习】分值融合方法

    2024-06-06 01:18:01       28 阅读
  3. golang普通函数与闭包函数使用示例

    2024-06-06 01:18:01       30 阅读
  4. 【程序填空题】矩阵(运算符重载)

    2024-06-06 01:18:01       27 阅读
  5. Vue前端如何配合SpringBoot后端实现文件下载

    2024-06-06 01:18:01       30 阅读
  6. Pytorch 星号*放在tensor前的作用

    2024-06-06 01:18:01       27 阅读