首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 汽车 游戏 社会热点 开源推荐 医疗健康 归档 标签 关于

11行代码更好的SQL

摘要

Prela is a new query language being developed at UCLA RePL . The language is quite different from SQL, but its key ideas are very simple. In this short tutorial, we will build a toy version of Prela i...

the title The movie and year query are relations table
2026-08-30 1 阅读 约8分钟阅读 remywang
分享:
字号:
Prela 是 UCLA RePL 正在开发的一种新查询语言。该语言与 SQL 有很大不同,但其关键思想非常简单。在这个简短的教程中,我们将用 Python 构建一个 Prela 的玩具版本,以了解其核心原理。在本教程结束时,您将了解以下查询的工作原理: movie.where(company.s(country).eq( "[us]" ) & keywords.eq( "character-name-in-title" )) .select(title &cast.s(person).s(alias).s(text)) 您可能已经猜到它在做什么:该查询查找由美国公司制作的每部电影,并且在其标题中包含角色名称,并输出标题和每个演员的别名。请注意,SQL 中的等效查询跨越 20 多行。 Prela 的第一个特别之处是只有二元关系,即具有两列的表。乍一听这可能非常有限,但很容易将具有多列的宽表“二值化”。假设我们有一个电影表: ID 标题年份 646 教父 1972 478 七武士 1954 583 卡萨布兰卡 1942 我们可以将 3 列表分解为 3 个二元关系,每个关系将行号映射到列值: movie = Rel([( 646 , 0 ), ( 478 , 1 ), ( 583 , 2 )]) title = Rel([( 0 , "The Godfather" ), ( 1 , "Seven Samurai" ), ( 2 , "Casablanca" )]) Year = Rel([( 0 , 1972 ), ( 1 , 1954 ), ( 2 , 1942 )]) 本教程使用 snip 将代码单元连接到类似笔记本的环境中,并进行了更改一个单元格中的内容会反映在后面的单元格中。上面的 movie 、 title 和 Year 关系分别代表原始表的 ID 、 title 和 Year 列。请注意,行号在 title 和 Year 中排在第一位,而在 movie 中排在第二位(也不称为 ID )。稍后将清楚其原因。关注二元关系的动机是它们概括了函数。函数之所以强大,是因为它们可以组合,使它们成为程序的构建块。函数将每个输入映射到唯一的输出,而关系可以将输入映射到多个不同的输出。从某种意义上说,关系可以被视为非确定性函数。这一切都非常抽象,所以让我们回到我们的例子。为了简单起见,我们将重点关注将每个输入映射到一个输出的关系,即它们恰好都是函数。 “调用”关系归结为将该关系转换为字典并查找值: print ( dict (movie)[ 646 ], dict (title)[ 0 ], dict (year)[ 0 ]) 我们现在准备介绍 Prela 中第一个也是最重要的运算符,关系组合。函数组合的工作原理是首先应用一个函数,然后将另一个函数应用于输出。两个关系 r 和 s 的组合本身就是一个关系,首先将 x 与 r 映射以获得一些 y ,然后将 y 与 s 映射以获得最终的“输出”。这可以通过将 s 转换为字典 d ,迭代 r 中的 (x, y) 对,最后如果在 d 中找到 y 则输出 (x, d[y]) 来实现: def select(r, s): d = dict (s) return [ (x, d[y]) for x, y in r if y in d ] 使用我们的示例,下面的查询将电影与标题组合起来以获得映射每个电影 ID 的关系其标题: print (movie.select(title)) 尝试将标题更改为年份,看看会得到什么。当我们将多个 .select 调用链接在一起时,组合的力量才真正显现出来。假设我们添加一个将每部电影映射到其制作公司的外键列,以及另一个电影公司的表: ID 标题年份公司 ... ... ... 0 ... ... ... 1 ... ... ... 2 ID 名称国家 0 Paramount [us] 1 Toho [jp] 2 Warner Bros. [us] 以同样的方式分解,我们得到另外四个关系: company = Rel([( 0 , 0 ), ( 1 , 1 ), ( 2 , 2 ) )]) id2row = Rel([( 0 , 0 ), ( 1 , 1 ), ( 2 , 2 )]) name = Rel([( 0 , "派拉蒙" ), ( 1 , "东宝" ), ( 2 , "华纳兄弟" )]) 国家 = Rel([( 0 , "[us]" ), ( 1 , "[jp]" ), ( 2 , "[us]" )]) 然后,我们可以通过一系列 .select 调用找到电影制作公司的国家/地区,其中我们缩写为 .s : print (movie.s(company).s(id2row).s(country)) 因为通过外键加入几乎总是需要将 ID“解析”为一行,所以 Prela 会自动插入该步骤,以便我们可以编写以下内容:就像“电影的公司的国家”一样! print (movie.s(company).s(country)) 这也是本教程开头片段最后一行的cast.s(person).s(alias).s(text) 中发生的情况。到目前为止,每个查询都返回一列值。为了选择多个属性,我们引入了 & 运算符。其中 .select 将 r 的第二列与 s 的第一列进行匹配, & 将 r 和 s 连接到两者的第一列,然后将它们的第二列配对: def and_(r, s): d = dict (s) return [ (x, (y, d[x])) for x, y in r if x in d ] 所以 title &year 将每个电影行同时映射到它的两个属性:请注意,结果仍然是二元关系, & 只是将值嵌套到元组中。这意味着我们可以像任何其他关系一样继续组合它,w
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱