PostgreSQL LATERAL 的工作原理

2024-05-29 19:52

本文主要是介绍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 的查询示例

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

SELECTe.name,t.task
FROMemployees 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 | task1Alice | task2Bob   | task3Bob   | task4

使用 LATERAL 和 WHERE 子句

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

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

SELECTe.name,t.task
FROMemployees e,LATERAL jsonb_array_elements(e.tasks) AS t(task)
WHEREt.task->>'task' IN ('task1', 'task3');

结果集

 name  | task
-------|-------Alice | task1Bob   | task3

总结

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

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

是的,你可以使用相同的方法来处理具有多个字段的 JSON 数组。假设每个 JSON 对象都有两个字段 `task``priority`,你可以像这样修改查询来处理它:```sql
SELECTe.name,t.task,t.priority
FROMemployees e,LATERAL (SELECT (elem->>'task') AS task,(elem->>'priority') AS priorityFROM jsonb_array_elements(e.tasks) AS elem) AS t
WHEREt.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
SELECTe.name,t.task,t.priority
FROMemployees e,LATERAL (SELECT (elem->>'task') AS task,(elem->>'priority') AS priority,ROW_NUMBER() OVER () AS rnFROM jsonb_array_elements(e.tasks) AS elem) AS tleft join 
WHERE
t.rn = 1;

这篇关于PostgreSQL LATERAL 的工作原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1014488

相关文章

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

C#实现将Excel工作表拆分为多个窗格

《C#实现将Excel工作表拆分为多个窗格》在日常工作中,我们经常需要处理包含大量数据的Excel文件,本文将深入探讨如何在C#中利用强大的Spire.XLSfor.NET自动化实现Excel工作表的... 目录为什么需要拆分 Excel 窗格借助 Spire.XLS for .NET 实现冻结窗格(Fro

Java 队列Queue从原理到实战指南

《Java队列Queue从原理到实战指南》本文介绍了Java中队列(Queue)的底层实现、常见方法及其区别,通过LinkedList和ArrayDeque的实现,以及循环队列的概念,展示了如何高效... 目录一、队列的认识队列的底层与集合框架常见的队列方法插入元素方法对比(add和offer)移除元素方法

SQL 注入攻击(SQL Injection)原理、利用方式与防御策略深度解析

《SQL注入攻击(SQLInjection)原理、利用方式与防御策略深度解析》本文将从SQL注入的基本原理、攻击方式、常见利用手法,到企业级防御方案进行全面讲解,以帮助开发者和安全人员更系统地理解... 目录一、前言二、SQL 注入攻击的基本概念三、SQL 注入常见类型分析1. 基于错误回显的注入(Erro

Spring IOC核心原理详解与运用实战教程

《SpringIOC核心原理详解与运用实战教程》本文详细解析了SpringIOC容器的核心原理,包括BeanFactory体系、依赖注入机制、循环依赖解决和三级缓存机制,同时,介绍了SpringBo... 目录1. Spring IOC核心原理深度解析1.1 BeanFactory体系与内部结构1.1.1

MySQL 批量插入的原理和实战方法(快速提升大数据导入效率)

《MySQL批量插入的原理和实战方法(快速提升大数据导入效率)》在日常开发中,我们经常需要将大量数据批量插入到MySQL数据库中,本文将介绍批量插入的原理、实现方法,并结合Python和PyMySQ... 目录一、批量插入的优势二、mysql 表的创建示例三、python 实现批量插入1. 安装 PyMyS

C#借助Spire.XLS for .NET实现Excel工作表自动化样式设置

《C#借助Spire.XLSfor.NET实现Excel工作表自动化样式设置》作为C#开发者,我们经常需要处理Excel文件,本文将深入探讨如何利用C#代码,借助强大的Spire.XLSfor.N... 目录为什么需要自动化工作表样式使用 Spire.XLS for .NET 实现工作表整体样式设置样式配置

深入理解Redis线程模型的原理及使用

《深入理解Redis线程模型的原理及使用》Redis的线程模型整体还是多线程的,只是后台执行指令的核心线程是单线程的,整个线程模型可以理解为还是以单线程为主,基于这种单线程为主的线程模型,不同客户端的... 目录1 Redis是单线程www.chinasem.cn还是多线程2 Redis如何保证指令原子性2.

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、