pgsql中的lateral使用小结
pgsql中的lateral
- 什么是LATERAL
- 带有LATERAL的SQL的计算步骤
- LATERAL在OUTER JOIN中的使用限制(或定义限制)
- LATERAL的几个简单的例子
- 总结
举几个我经常使用的栗子
首先说下场景:
有个一个商品表goods,还有一个评价表evaluations。商品表和评价表是一对多的。
1、在一个后台,我想查询商品的信息,同时查询这个商品的评价的数量。
我们可以通过这样来实现
SELECT
g.*,
COUNT(e.*) as num
FROM goods as g
LEFT JOIN evaluation as e on e.goods_id=g.id
WHERE = GROUP BY g.id
通过左连接,加上分组就能实现了
那么也可以使用lateral来实现
SELECT
g.*,
e.num
FROM goods as g
LEFT JOIN LATERAL(
SELECT COUNT(ev.id) as num FROM evaluation AS ev
WHERE ev.goods_id=g.id
) AS e ON TRUE
WHERE =
就这样好像lateral的优势不是那么明显。
2、我们查询评论数目大于3的商品的信息
SELECT
g.*,
COUNT(e.*) as num
FROM goods as g
LEFT JOIN evaluation as e on e.goods_id=g.id
HAVING COUNT(e.*)> GROUP BY g.id
这样就不行了,查询不到了。
这时候就需要使用LATERAL
SELECT
g.*,
e.num
FROM goods as g
LEFT JOIN LATERAL(
SELECT COUNT(ev.id) as num FROM evaluation AS ev
WHERE ev.goods_id=g.id
) AS e ON TRUE
WHERE = AND num>
3、然后我们再次查询这些商品的信息,希望找到黄金会员评论的商品信息
这时候LATERAL的优势就更加明显了
SELECT
g.*,
e.num
FROM goods as g
LEFT JOIN LATERAL(
SELECT COUNT(ev.id) as num
FROM evaluation AS ev
LEFT JOIN users u on u.id=ev.user_id
WHERE ev.goods_id=g.id AND u.grade=
) AS e ON TRUE
WHERE = AND num>
什么是LATERAL
我们先来看官方对lateral的定义
可以在出现于FROM中的子查询前放置关键词LATERAL。这允许它们引用前面的FROM项提供的列(如果没有 LATERAL,每一个子查询将被独立计算,并且因此不能被其他FROM项交叉引用)。
出现在FROM中的表函数的前面也可以被放上关键词LATERAL,但对于关键词的不可选的,在任何情况下函 数的参数都可以包含前面FROM项提供额列的引用。
一个LATERAL项可以出现在FROM列表项层,或者出现在一个JOIN树中。在后者如果出现在JOIN的右部, 那么可以引用在JOIN左部分的任何项。
如果一个FROM项包含LATERAL交叉引用,计算过程中:对于提供交叉引用列的FROM项的每一行,或者 多个提供这些列的多个FROM项进行集合,LATERAL项将被使用该行或者行集中的列值进行计算。得到结 果行将和它们被计算出来的行进行正常的连接。对于来自这些列的源表的每一行或行集,该过程将重复。
手册上提到:
SELECT * FROM foo, LATERAL (SELECT * FROM bar WHERE bar.id = foo.bar_id) ss; 在 LATERAL (这里可以关联(引用)lateral左边的表或子句) 所以允许: LATERAL (SELECT * FROM bar WHERE bar.id = foo.bar_id)
带有LATERAL的SQL的计算步骤
1、逐行提取被lateral子句关联(引用)的FROM或JOIN的ITEM(也叫source table)的记录(s) 中的column(s)
for each row of the FROM item providing the cross-referenced column(s),
or set of rows of multiple FROM items providing the columns,
2、使用以上提取的columns(s),关联计算lateral子句中的ITEM
the LATERAL item is evaluated using that row or row set'us values of the columns.
3、lateral的计算结果row(s),与所有from,join ITEM(S)正常的进行join计算 The resulting row(s) are joined as usual with the rows they were computed from.
4、从1到3开始循环,直到所有的source table的行取尽。
This is repeated for each row or set of rows from the column source table(s).
LATERAL在OUTER JOIN中的使用限制(或定义限制)
由于lateral的计算步骤是从source table逐条展开的,所以OUTER JOIN时只能使用source table 作为whole端,LATERAL内的ITEM不能作为WHOLE端。
因此lateral只能在left join的右边。或者right join的左边。因此不能是WHOLE端。
The column source table(s) must be INNER or LEFT joined to the LATERAL item, else there would not be a well-defined set of rows from which to compute each set of rows for the LATERAL item. Thus, although a construct such as X RIGHT JOIN LATERAL Y is syntactically valid, it is not actually allowed for Y to reference X.
LATERAL的几个简单的例子
1、
A trivial example of LATERAL is
SELECT * FROM foo, LATERAL (SELECT * FROM bar WHERE bar.id = foo.bar_id) ss;
This is not especially useful since it has exactly the same result as the more conventional
SELECT * FROM foo, bar WHERE bar.id = foo.bar_id;
一个LATERAL项可以出现在FROM列表项层
2、
LATERAL is primarily useful when the cross-referenced column is necessary for computing the row(s) to be joined. A common application is providing an argument value for a set-returning function. For example, supposing that vertices(polygon) returns the set of vertices of a polygon, we could identify close-together vertices of polygons stored in a table with:
SELECT p1.id, p2.id, v1, v2
FROM polygons p1, polygons p2,
LATERAL vertices(p1.poly) v1,
LATERAL vertices(p2.poly) v2
WHERE (v1 <-> v2) < AND p1.id != p2.id;
This query could also be written
SELECT p1.id, p2.id, v1, v2
FROM polygons p1 CROSS JOIN LATERAL vertices(p1.poly) v1,
polygons p2 CROSS JOIN LATERAL vertices(p2.poly) v2
WHERE (v1 <-> v2) < AND p1.id != p2.id;
函数调用,支持应用函数左边的ITEM(S)。所以可以看消除LATERAL,语义是一样的。
(As already mentioned, the LATERAL key word is unnecessary in this example, but we use it for clarity.)
3、
It is often particularly handy to LEFT JOIN to a LATERAL subquery, so that source rows will appear in the result even if the LATERAL subquery produces no rows for them. For example, if get_product_names() returns the names of products made by a manufacturer, but some manufacturers in our table currently produce no products, we could find out which ones those are like this:
SELECT m.name
FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true
WHERE pname IS NULL;
lateral的查询结果也是可以作为整个语句的查询条件的
总结
1、lateral 可以出现在FROM的列表项层,也可以出现在JOIN数树中,如果出现在JOIN的右部分,那么 可以引用在JOIN左部分的任何项。
2、由于lateral的计算步骤是从source table逐条展开的,所以OUTER JOIN时只能使用source table 作为whole端,LATERAL内的ITEM不能作为WHOLE端。
3、LATERAL 关键词可以在前缀一个 SELECT FROM 子项. 这能让 SELECT 子项在FROM项出现之前就引 用到FROM项中的列. (没有 LATERAL 的话, 每一个 SELECT 子项彼此都是独立的,因此不能够对其 它的 FROM 项进行交叉引用.)
4、当一个 FROM 项包含 LATERAL 交叉引用的时候,查询的计算过程如下: 对于FROM项提供给交叉引 用列的每一行,或者多个FROM像提供给引用列的行的集合, LATERAL 项都会使用行或者行的集合的列 值来进行计算. 计算出来的结果集像往常一样被加入到联合查询之中. 这一过程会在列的来源表的行或 者行的集合上重复进行.
参考
【PostgreSQL 9.3 add LATERAL support - LATERAL的语法和用法介绍】https://github.com/digoal/blog/blob/master/201210/20121008_01.md?spm=a2c4e.10696291.0.0.408619a4cXorB6&file=20121008_01.md
【LATERAL】https://www.postgresql.org/docs/devel/queries-table-expressions.html#QUERIES-LATERAL
pgsql中的lateral使用小结的更多相关文章
- Delphi中ClientDataSet的用法小结
Delphi中ClientDataSet的用法小结 TClientDataSet控件继承自TDataSet,其数据存储文件格式扩展名为 .cds,是基于文件型数据存储和操作的控件.该控件封装了对数据进 ...
- EntityFramework中几种操作小结
目前项目中使用到的EntityFramework中几种操作小结,先标记下.没有详细介绍,后续有空的话再补充一些并完善一下. 列中加入RowVersion时间戳 public class Product ...
- 关于 C# 中接口的一些小结
< 关于 C# 中“接口”的一些小结 > 对于 C# 这样的不支持多重继承的语言,很好的体现的层次性,但是有些时候多重继承的确有一些用武之地. 比如,在 Stream 类 . 图形设备 ...
- hive中的lateral view 与 explode函数的使用
hive中的lateral view 与 explode函数的使用 背景介绍: explode与lateral view在关系型数据库中本身是不该出现的. 因为他的出现本身就是在操作不满足第一范式的数 ...
- C#中SqlDataAdapter的使用小结---转载
C#中SqlDataAdapter的使用小结 转载 叁木-Neil 最后发布于2018-06-07 21:29:39 阅读数 8275 收藏 展开 SqlDataAdapter对象 一.特点介绍1.表 ...
- pgsql中的行锁
pgsql中的行锁 前言 用户可见的锁 regular Lock 行级别 FOR UPDATE FOR NO KEY UPDATE FOR SHARE FOR KEY SHARE 测试下加锁之后的数据 ...
- pgsql中的事务隔离
pgsql中的事务隔离级别 前言 事物隔离级别 在各个级别上被禁止出现的现象是 脏读 不可重复读 幻读 序列化异常 读已提交隔离级别 可重复读隔离级别 可序列化隔离级别 摘录 pgsql中的事务隔离级 ...
- windows中抓取hash小结(下)
书接上回,windows中抓取hash小结(上) 指路链接 https://www.cnblogs.com/lcxblogs/p/13957899.html 继续 0x03 从ntds.dit中抓取 ...
- windows中抓取hash小结(上)
我上篇随笔说到了内网中横向移动的几种姿势,横向移动的前提是获取了具有某些权限的用户的明文密码或hash,正愁不知道写点啥,那就来整理一下这个"前提"-----如何在windows系 ...
随机推荐
- 【Weiss】【第03章】练习3.4、3.5:有序链表求交、并
[练习3.4] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∩L2的过程. [练习3.5] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∪L2的过程. 思路比较简单,测 ...
- java之AQS和显式锁
本次内容主要介绍AQS.AQS的设计及使用.ReentrantLock.ReentrantReadWriteLock以及手写一个可重入独占锁 1.什么是AQS? AQS,队列同步器AbstractQu ...
- Journal of Proteome Research | Mining the Proteome Associated with Rheumatic and Autoimmune Diseases(挖掘风湿和自身免疫疾病相关的蛋白组)(解读人:黄旭蕾)
期刊名:JPR 发表时间:(2019年12月) IF:3.780 单位:Grupo de Investigación de Reumatología (GIR), Unidad de Proteó ...
- 后端开发使用pycharm的技巧
后端开发使用pycharm的技巧 目录 后端开发使用pycharm的技巧 1.使用说明 2.database 3.HTTP Client 1.使用说明 首先说明,本文所使用的功能为pycharm专业版 ...
- hdu2112 dijkstra
题目链接:http://icpc.njust.edu.cn/Problem/Hdu/2112/ 只要需处理一下字符串,给他个编号再跑一半dijkstra就行. 代码如下: #include<bi ...
- ML Lecture 0-2: Why we need to learn machine learning?
在Github上也po了这个系列学习笔记(MachineLearningCourseNote),觉得写的不错的小伙伴欢迎来给项目点个赞哦~~ ML Lecture 0-2: Why we need t ...
- ArcGIS Server的安装
1.双击ArcGIS Server安装目录下的Setup.exe. 2.点击“Next”. 3.选择“I accept the license agreement”,点击“Next”. 4.点击“Ch ...
- 使用tensorflow的softmax进行mnist识别
tensorflow真是方便,看来深度学习需要怎么使用框架.如何建模- ''' softmax classifier for mnist created on 2019.9.28 author: vi ...
- __str_方法和__repr__的区别
__str__方法和__repr__方法: 官方文档解释: Object.__repr__(self): 由 repr() 内置函数调用以输出一个对象的“官方”字符串表示.如果可能,这应类似一个有效的 ...
- Linux上的软件安装有哪些方式?
Linux上的软件安装有以下几种常见方式介绍 1.二进制发布包 软件已经针对具体平台编译打包发布,只要解压,修改配置即可 2.RPM包 软件已经按照redhat的包管理工具规范RPM进行打包发布,需要 ...