当前位置:网站首页>使用MULTISET来比较数据集的实例介绍
使用MULTISET来比较数据集的实例介绍
2022-07-30 19:33:00 【JAVAQXQ】
使用普通SQL可能更难解决的问题是这样的问题:
哪些电影与给定的电影X有相同的演员?
像往常一样,我们在这个例子中使用sakila数据库。用SQL(例如PostgreSQL,具体来说)解决这个问题的可能方式是什么?下面的查询给出了每部电影的演员概况:
SELECT film_id, array_agg(actor_id ORDER BY actor_id) actors FROM film_actor GROUP BY film_id 复制代码
它产生的结果是这样的:
|film_id|actors |
|-------|----------------------------------|
|1 |{1,10,20,30,40,53,108,162,188,198}|
|2 |{19,85,90,160} |
|3 |{2,19,24,64,123} |
|4 |{41,81,88,147,162} |
|5 |{51,59,103,181,200} |
|6 |{21,23,62,108,137,169,197} |
|... |... |
复制代码请注意,在SQL中,数组的行为就像列表一样,也就是说,它们保持着自己的排序,所以明确地对数组进行排序对于能够相互比较演员是很重要的。现在,我们想从上面找到所有共享相同演员集的电影:
WITH t AS (
-- Previous query
SELECT
film_id,
array_agg(actor_id ORDER BY actor_id) actors
FROM film_actor
GROUP BY film_id
)
SELECT
array_agg(film_id ORDER BY film_id) AS films,
actors
FROM t
GROUP BY actors
ORDER BY count(*) DESC, films
复制代码结果就是现在:
|films |actors |
|--------|----------------------------------|
|{97,556}|{65} |
|{1} |{1,10,20,30,40,53,108,162,188,198}|
|{2} |{19,85,90,160} |
|{3} |{2,19,24,64,123} |
|{4} |{41,81,88,147,162} |
|{5} |{51,59,103,181,200} |
|{6} |{21,23,62,108,137,169,197} |
|... |... |
复制代码所以,我们可以看到,只有2部电影共享相同的演员集,这些电影是 FILM_ID IN (97, 556) 。(Sakila数据库有点无聊,因为数据集是生成的)。
使用MULTISET比较
虽然上面的内容已经相当酷了,但在这篇文章中,我想展示一下 jOOQ 3.15 MULTISET 支持的 一个鲜为人知的功能,即它们可以相互比较的事实。
而且正如SQL标准 MULTISET 的性质一样,排序是不相关的,所以我们不需要为这种比较添加任何明确的 ORDER BY 子句。事实上,这并不是100%的不相关。你 可以 为投影目的对 MULTISET ,所以排序将由jOOQ维护。但是当你在谓词中使用它们时,jOOQ将覆盖你的 ORDER BY 子句。
使用jOOQ,我们可以写:
ctx.select(FILM.FILM_ID, FILM.TITLE)
.from(FILM)
.where(
multiset(
select(FILM_ACTOR.ACTOR_ID)
.from(FILM_ACTOR)
.where(FILM_ACTOR.FILM_ID.eq(FILM.FILM_ID))
).eq(multiset(
select(FILM_ACTOR.ACTOR_ID)
.from(FILM_ACTOR)
.where(FILM_ACTOR.FILM_ID.eq(97L))
))
)
.orderBy(FILM_ID)
.fetch();
复制代码这比前一种形式的查询效率低一些,因为它从两个子查询中访问 FILM_ACTOR 表,尽管其中只有一个是相关的。使用默认的 JSONB 仿真,可以生成以下查询:
SELECT film.film_id, film.title
FROM film
WHERE (
SELECT coalesce(
jsonb_agg(jsonb_build_array(v0) ORDER BY t.v0),
jsonb_build_array()
)
FROM (
SELECT film_actor.actor_id AS v0
FROM film_actor
WHERE film_actor.film_id = film.film_id
) AS t
) = (
SELECT coalesce(
jsonb_agg(jsonb_build_array(v0) ORDER BY t.v0),
jsonb_build_array()
)
FROM (
SELECT film_actor.actor_id AS v0
FROM film_actor
WHERE film_actor.film_id = 97
) AS t
)
ORDER BY film.film_id
复制代码我承诺,对于 MULTISET ,不需要 ORDER BY 子句,对于jOOQ代码来说,这仍然是真实的。然而,在幕后,jOOQ必须按JSON数组的内容排序,以确保两个 MULTISET 的值是相同的,无论其顺序如何。
其结果是与前面的结果显示的两个ID相同:
+-------+--------------+ |film_id|title | +-------+--------------+ | 97|BRIDE INTRIGUE| | 556|MALTESE HOPE | +-------+--------------+ 复制代码
比较MULTISET_AGG,而不是
如果你喜欢使用连接和 GROUP BY 来生成电影的演员 MULTISET ,你也可以用jOOQ来做。这一次,我们使用的是
- 隐式连接来简化对
FILM.TITLE的访问,从FILM_ACTOR - 在
HAVING子句中的一个MULTISET谓词,使用MULTISET_AGG
下面是jOOQ的版本:
ctx.select(FILM_ACTOR.FILM_ID, FILM_ACTOR.film().TITLE)
.from(FILM_ACTOR)
.groupBy(FILM_ACTOR.FILM_ID, FILM_ACTOR.film().TITLE)
.having(multisetAgg(FILM_ACTOR.ACTOR_ID).eq(multiset(
select(FILM_ACTOR.ACTOR_ID)
.from(FILM_ACTOR)
.where(FILM_ACTOR.FILM_ID.eq(97L))
)))
.orderBy(FILM_ACTOR.FILM_ID)
.fetch();
复制代码后退,生成的SQL看起来像这样:
SELECT film_actor.film_id, alias_75379701.title
FROM film_actor
JOIN film AS alias_75379701
ON film_actor.film_id = alias_75379701.film_id
GROUP BY film_actor.film_id, alias_75379701.title
HAVING jsonb_agg(
jsonb_build_array(film_actor.actor_id) ORDER BY film_actor.actor_id
) = (
SELECT coalesce(
jsonb_agg(jsonb_build_array(v0) ORDER BY t.v0),
jsonb_build_array()
)
FROM (
SELECT film_actor.actor_id AS v0
FROM film_actor
WHERE film_actor.film_id = 97
) AS t
)
ORDER BY film_actor.film_id
复制代码请注意隐式连接是如何自动展开的,而 HAVING 谓词再次使用了通常的 JSONB 仿真,用于 MULTISET 和 MULTISET_AGG 。
替代方法
在上面的例子中,我们比较了投射单列的 MULTISET 表达式,换句话说, Result<Record1<Long>> 嵌套集合类型。jOOQ将始终确保你的查询类型检查和生成的SQL是正确的。
使用 MULTISET 的一个替代方法是使用 ARRAY_AGG 和 ARRAY (现在你必须再次明确 ORDER BY )。用jOOQ:
ctx.select(FILM_ACTOR.FILM_ID, FILM_ACTOR.film().TITLE)
.from(FILM_ACTOR)
.groupBy(FILM_ACTOR.FILM_ID, FILM_ACTOR.film().TITLE)
.having(arrayAgg(FILM_ACTOR.ACTOR_ID)
.orderBy(FILM_ACTOR.ACTOR_ID).eq(array(
select(FILM_ACTOR.ACTOR_ID)
.from(FILM_ACTOR)
.where(FILM_ACTOR.FILM_ID.eq(97L))
.orderBy(FILM_ACTOR.ACTOR_ID)
)))
.orderBy(FILM_ACTOR.FILM_ID)
.fetch();
复制代码使用SQL:
SELECT film_actor.film_id, film.title
FROM film_actor
JOIN film
ON film_actor.film_id = film.film_id
GROUP BY film_actor.film_id, film.title
HAVING array_agg(film_actor.actor_id ORDER BY film_actor.actor_id) =
ARRAY (
SELECT film_actor.actor_id
FROM film_actor
WHERE film_actor.film_id = 97
ORDER BY film_actor.actor_id
)
ORDER BY film_actor.film_id
复制代码边栏推荐
- M3SDA:用于多源域自适应的矩匹配
- 阿里面试官:给我描述一下缓存击穿的现象,并说说你的解决思路?
- iPhone真是十三香?两代产品完全对比,或许上一代更值得买
- Vulkan开启特征(feature)的正确姿势
- What is a RESTful API?
- Range.CopyFromRecordset method (Excel)
- SimpleOSS third-party library libcurl and engine libcurl error solution
- 【MindSpore】多卡训练保存权重问题
- ImportError: attempted relative import with no known parent package
- 055 c# print
猜你喜欢

MySQL数据库 ---MySQL表的增删改查(进阶)

Golang logging library zerolog use record
![[hbuilder] cannot run some projects, open the terminal and cannot enter commands](/img/fa/63f36683d090558f3fe5f582d86ca0.png)
[hbuilder] cannot run some projects, open the terminal and cannot enter commands

VBA connects Access database and Excel

How to build FTP server under win2003

Different lower_case_table_names settings for server (‘1‘) and data dictionary (‘0‘) 解决方案

VBA 连接Access数据库和Excle
![[PyTorchVideo Tutorial 01] Quickly implement video action recognition](/img/1a/696c5722bb94fabd688a8714ae2e8c.png)
[PyTorchVideo Tutorial 01] Quickly implement video action recognition

VBA batch import Excel data into Access database

MySQL mass production of data
随机推荐
mysql慢查询优化
Linux下最新版MySQL 8.0的下载与安装(详细步骤)
LeetCode 0952.按公因数计算最大组件大小:建图 / 并查集
牛客刷题系列之进阶版(搜索旋转排序数组,链表内指定区间反转)
mysql8 installation under linux
Encapsulates a console file selector based on inquirer
架构师如何成长
The advanced version of the cattle brushing series (search for rotating sorted arrays, inversion of the specified range in the linked list)
MindSpore: CV.Rescale(rescale,shift)中参数rescale和shift的含义?
Correct pose of Vulkan open feature
谷歌AlphaFold近日宣称预测出地球上几乎所有蛋白质结构
Install MySQL tutorial under Linux
MindSpore:Cifar10Dataset‘s num_workers=8, this value is not within the required range of [1, cpu_thr
Perfectly Clear QuickDesk & QuickServer图像校正优化工具
Another company interview
MySQL performance optimization (hardware, system configuration, table structure, SQL statements)
深入浅出边缘云 | 3. 资源配置
VBA batch import Excel data into Access database
MindSpore:【语音识别】DFCNN网络训练loss不收敛
MySQL性能优化(硬件,系统配置,表结构,SQL语句)