谷歌内部推出 SQL 中的管道(Pipe)语法

SQL 有问题。我们可以解决这些问题:SQL 中的管道(Pipe)语法(via) 谷歌研究院(Google Research)的一篇新论文描述了分析型 SQL 查询的自定义语法,该语法自今年 2 月起在谷歌内部推出,到 2024 年 8 月将达到 1,600 名 “七日活跃用户”。

其中的一个关键想法是解决标准 SQL 最大的可用性问题之一:查询中子句的顺序。以 SELECT 而不是 FROM 开头一直令人困惑,请参阅 Julia Evans 撰写的《SQL 查询不要以 SELECT 开头》。

下面是一个新替代语法的示例,摘自上周添加到谷歌开源 ZetaSQL 项目中的 Pipe 查询语法文档

对于这个 SQL 查询:

SELECT component_id, COUNT(*)
FROM ticketing_system_table
WHERE
  assignee_user.email = 'username@email.com'
  AND status IN ('NEW', 'ASSIGNED', 'ACCEPTED')
GROUP BY component_id
ORDER BY component_id DESC;

The Pipe query alternative would look like this:

FROM ticketing_system_table
|> WHERE
    assignee_user.email = 'username@email.com'
    AND status IN ('NEW', 'ASSIGNED', 'ACCEPTED')
|> AGGREGATE COUNT(*)
   GROUP AND ORDER BY component_id DESC;

谷歌研究论文以两栏 PDF 格式发布。我曾在 Hacker News 上对此嗤之以鼻:

谷歌:你是一家网络公司。请学会以网页形式发布研究论文。

这一直是我的一个心病。这样的 PDF 文件在手机上很难阅读,很难复制粘贴,可访问性很差(参见 Mastodon 对话),总之就是网络的坏公民。

在抱怨过这个问题后,我觉得有必要看看自己能否解决这个问题。谷歌自己的 Gemini Pro 1.5 模型可以处理 PDF,因此我将 PDF 上传到谷歌 AI Studio,并像这样提示 gemini-1.5-pro-exp-0801 模型:

将此文档转换为样式整齐的语义 HTML

效果出奇的好。它输出了大约一半文档的 HTML,然后停了下来,估计是遇到了输出长度限制,但后续的 “其余部分 ”提示又让它从停止的地方继续运行,直到最后。

下面是结果(我在顶部添加了一个横幅,说明这是一个转换): Pipe-Syntax-In-SQL.html

我还没有将两者完全比较过,所以不能保证没有遗漏或错误。

PDF 中的数字并不存在–Gemini Pro 输出的标记如 <img src=“figure1.png” alt=”图 1:SQL 语法子句顺序与语义评估顺序不匹配。(摘自 [25])”>,但却无法帮助我创建这些图像。

有趣的是,文档的结尾是 <p>(一长串参考文献,为了节省篇幅,我就不在这里复制了)</p>,而不是真正包含论文中的参考文献!

因此,这并不是一个完美的解决方案,但考虑到这只是我所能想到的第一个提示,它是一个非常有希望的开端。我希望有人愿意多花几分钟时间,在 Gemini Pro 的帮助下制作出非常有用的 HTML 论文替代版本。

最后还有一件有趣的事:几个小时前,我在 Hacker News 上发布了一个链接。就在刚才,当我在 Google 上搜索这篇论文的确切标题时,我的 HTML 版本已经排在了搜索结果的第三位!

我现在已经在 HTML 的顶部添加了一个 <meta name=“robots” content=“noindex, follow”> 标签,以防止这些未经验证的人工智能泔水进入他们的搜索索引。这很好地提醒我们,HTML 比 PDF 更适合在网络上共享信息!

 

本文文字及图片出自 SQL Has Problems. We Can Fix Them: Pipe Syntax In SQL

你也许感兴趣的:

共有 187 条讨论

  1. SQLite 的创建者理查德-希普(Richard Hipp)在一个实验分支中实现了这一功能:https://sqlite.org/forum/forumpost/5f218012b6e1a9db

    值得一读,其中有一些很好的见解。看起来,他将等待 Postgres 在发布之前主动实现这一功能。

    1. 他解释为什么不急于在 SQLite 中添加未经验证的新 SQL 语法时的评论非常精彩:

      > 我的目标是在 2050 年之前保持 SQLite 的相关性和可行性。这距离现在还有很长一段时间。如果我知道标准 SQL 从现在到那时不会有任何变化,我就会继续进行非标准扩展,允许 FROM-clause-first 查询,因为这似乎是一个有用的扩展。问题是标准 SQL 不会一成不变。也许未来某个版本的 “标准 SQL ”会支持某种 FROM-clause-first 查询格式。我需要确保无论 SQLite 支持什么,都能与标准兼容。要做到这一点,唯一的办法就是在标准出现之前什么都不支持。

      1. 它的雄心壮志几乎让人厌烦,正是这样一个项目的正确管理者

        1. 希普博士是我的偶像之一。他似乎在半默默无闻的状态下默默耕耘了几十年,最后却开发出了一些令人惊叹的软件。我对他为了在 RFQ 上打勾而使用基督教修道院的生活准则作为 SQLite 的道德规范(libsql fork 的部分后果)所引起的争论感到很有趣,因为他看起来确实像个程序员僧侣。 值得一提的是,作为一个不可知论者,我读过几遍这些准则,觉得没有什么不妥。虽然我认为这场闹剧没有必要,但 libsql 的人们正在做着有趣的工作)。

          我选择永远不与此人见面,并打消这个念头。继续努力吧,博士。

          1. 平心而论,我认为人们对这个调侃式的 “行为准则 ”的不满在于,如果将其视为真正的行为准则(即 SQLite 贡献者为参与项目而必须遵守的一系列规则),那么它显然是不合适的。举例来说,Hipp 博士似乎不太可能希望排除通奸或不经常祈祷的贡献者。

            (以前的行为准则现在被称为 “道德准则”,而 SQLite 目前还没有正式的 CoC)。

            1. 在我看来,他们似乎有不相容的愿景(SQLite 希望在 2050 年的传统使用环境中运行,而 libsql 则希望现代化并向最新的使用环境靠拢),因此分叉是适当且不可避免的做法。

              鉴于 SQLite 并不对贡献开放(这也是 libsql 的苦恼之一),我并不担心他们没有制定明确的行为准则。在我看来,在资源库(ETA: the website, rather)中挖掘一个令人讨厌的复活节彩蛋,然后把它当作一个严肃的问题来链接,这是不应该的。老实说,我觉得这些抱怨不应该完全被排除在他们的公告之外–他们对自己的分叉有一个很酷的愿景,而这些抱怨只会分散他们的注意力。

              1. 是的,SQLite 并不是一个采用开放贡献模式的项目,这一点很重要。不过,据推测他们确实接受外部贡献,如错误报告、建议补丁等。

                你不需要翻遍软件仓库就能找到 CoC。它就在网站 /codeofconduct.html 上:https://web.archive.org/web/20180315125217/https://www.sqlit…

                1. Hipp 博士的另一个很酷的项目是化石 SCM,SQLite 就是在这个项目中开发的,它的一个特点是带有类似 GitHub 的网页视图。网站实际上就是 repo 的网页视图。(抱歉表达得有点混乱,我知道它在网站上,但我把网站说成了版本库)。

              2. 如果作者是唯一的贡献者,那么文件中明目张胆的宗教歧视就完全不是问题(我想作者一定是以某种形式的公平方式从不负责任的实体那里获得外部支持;我不知道《行为准则》理论的细节),否则就完全不可接受。

                根据文件本身,如果打算将其他人包括进来,就应该重写,而且应该明确说明目前的形式只适用于作者本人。

    2. FROM第一将是不可思议的。我只能寄希望于 Postgres 和其他公司能够团结起来,将这种扩展标准化!

      1. 是的,我不知道 DuckDB 已经支持它了!

        能够以任意顺序从 WHERE 中进行 SELECT FROM,允许多个 WHERE 和 AGGREGATE 等,再加上支持尾部逗号,使得复制粘贴模板、重复使用和生成代码的 SQL 变得更加容易。

          FROM table  <-- at this point there is an implicit SELECT *
          SELECT whatever
          WHERE some_filter
          WHERE another_filter <-- this is like AND
          AGGREGATE something
          WHERE a_filter_that_is_after_grouping <-- is like HAVING
          ORDER BY ALL <-- group-by-all is great in engines that support it; want it for ordering too

        1. HAVING 这样的特殊关键字可以防止输入错误的行。

          这个 WHERES 的 OR 是如何实现的?

        2. 什么是 group-by-all?听起来像 distinct?

          1. 它与区分不同。区分只是消除重复,但不会对条目进行分组。

            假设…

              SELECT brand, model, revision, SUM(quantity)
               FROM stock
               GROUP BY brand, model, revision
            

            使用 “区分 ”无法解决这个问题,因为您无法获得正确的计数。

            Group By All 可以让您写得更紧凑一些…

              SELECT brand, model, revision, SUM(quantity)
               FROM stock
               GROUP BY ALL
            1. 找到你了 谢谢。这其实超级有用!遗憾的是,Postgres 好像没有实现这个功能。

              当我在乱翻的时候,我会恢复 “按 1、2、3……分组”。如果能按全部分组,肯定会有很大改进。

          2. 通常情况下,SELECT 会有一堆要分组的列和一堆聚合列。然后,在 GROUP BY 子句中,必须列出所有要分组的列。查询编译器知道是哪些列,并会对你进行控制,确保你的操作正确无误。而 GROUP BY ALL 所做的只是说 “编译器知道,没必要列出所有列”。非常方便。

            BigQuery 支持 GROUP BY ALL,它可以真正清理大量查询。例如

             SELECT foo, bar, SUM(baz)
               FROM x
               GROUP BY ALL <-- 等同于 GROUP BY foo, bar
            

            (嗯,MySQL 除外;在我的记忆中,MySQL 会对任何不是显式聚合函数但没有分组的列默默地执行 ANY_VALUE();唉,那是很久以前的事了)

            1. MySQL 已经不再这样做了;ONLY_FULL_GROUP_BY 模式在 5.7(我想)中成为默认模式。不过你仍然可以关闭它,获得以前的行为。

      2. 将 FROM 设为第二项而不是第一项的历史究竟是怎样的?因为 FROM 在前似乎更直观,而且实际上也是你编写查询的方式。

        我真的希望这能得到更广泛的采用,因为我真的不想再这么做了:

          SELECT *
          FROM all_the_joins
        

        into

          SELECT {my statements here}
          FROM all_the_joins
    3. 有趣的是,他把新语法称为 “from-clause-first”。就像一个价值很低的小改动。

      1. 我认为这一点很重要,因为很多概念都被表述得过于复杂;例如,函数式编程在我的脑海中是有道理的,但如果你把它表述为 lambda 微积分,并用新的运算符以简洁的形式写出来,你就失去了我的兴趣。

  2. LINQ、PRQL、Kusto 都在这之前。

    LINQ 主要限于 .NET,而 PRQL 则不然。https://prql-lang.org/

    这是业界值得欢迎的变化。

    早在几年前我就做出过这样的预测:https://x.com/tehlike/status/1517533067497201666

    1. 本文直接引用了 PRQL 和 Kusto。这里的主要目标是从早期的努力中吸取经验教训,并尝试找到一种在现有 SQL 语法内部和旁边工作的语法,而不是作为一种完全独立的语言。

      1. 自从 PRQL 首次在 HN 上获得广泛关注以来,我已经关注它有一段时间了,我非常喜欢它,但我真的希望谷歌的管道语法能够大放异彩,原因有以下几点:

        1. 与你提到的情况类似,虽然我认为如果你了解 SQL,PRQL 还是很容易上手的,但它仍然给人一种全新语言的 “感觉”。这种管道式 SQL 语法让我立刻感觉棒极了–它映射了我的大脑对查询的思考方式(本质上是将数据通过一连串的筛选和转换),但我所有的 SQL 知识都感觉是原封不动地搬过来的。

        2. 我觉得我现在已经足够老了,知道采用在现有技术基础上逐步改进的新技术,最关键的是要让升级路径尽可能简单。我不希望一下子把所有的东西都翻个底朝天,但我只希望能够每次一小块一小块地进行升级。虽然不是百分之百的一回事,但如果你看看 IPv6 等著名技术的糟糕使用情况,以及使用 NPM ES 模块发行版的痛苦,最大的痛点就是这些技术让你不得不进行 “全有或全无 ”的迁移–它们没有一种从 A 点到 B 点的简单易行的方法。如果使用 PRQL,我对在现有项目中混合使用 SQL 和 PRQL 的热情就会大打折扣。

      2. 企业和互联世界已经不再强迫现代项目与 COBOL 兼容,但仍坚持要求与 SQL 兼容,这太疯狂了。

    2. 我是 kusto 的忠实用户,在查询语言中加入管道功能真是太棒了。

      如果你还没试过,那就太好了!

      1. 我还没试过,但我以前是一名 .net 开发人员,经常使用 LINQ(并为 NHibernate 及其 Linq 提供商做出了一些贡献),我是这种方法的忠实粉丝。

        Kusto 看起来也很有趣,我想我想构建的一些东西会用到它!

        1. LINQ 真是难以置信的直观。我想知道这是否会让为支持这种语法的数据库创建 C# LINQ 提供程序变得更容易。

      2. 确实如此。Elastic 最近也发布了一种名为 ES|QL 的管道式查询语言。感觉与 Kusto 相似。

        我发现管道式查询既更容易编写,也更容易读取。

    3. 没有 LINQ 在任何地方都很不方便。大多数语言都有一些库试图破解类似的东西,但通常根本无法实现。

      1. 如果不需要兼容任何东西,那么设计一个好的 DSL 就容易多了

        1. .NET在几十年前就已经被大量使用了。

    4. “from “关键词是源自.NET(2007 年的框架 3.5),还是在研究中就已经存在了?

  3. > 这仍然是我长期以来的一个心病。这样的 PDF 文件在手机上很难阅读,也很难复制粘贴……

    我一直不明白为什么从数字原生 PDF(直接从数字源文件创建,而不是通过 OCR 扫描图像)中复制文本的体验往往如此糟糕。即使是用 LaTex 制作的 PDF,在复制的文本中也经常包含不理想的连字符,如 fi 和 fl。从一些 Springer 期刊上复制的文本有时会在单词之间缺少空格,或者在单词的字母之间引入不必要的空格…… 这是 PDF 技术固有的问题吗?

    1. > 这是 PDF 技术固有的问题吗?

      没错。PDF 的指令并不是 “在这个方框中呈现这段文字”,而是 “在每个 x、y 坐标处呈现每个字形”。

      它在设计之初就不是为了提取文本。因此,要将其转换成文本,就需要大量的启发式方法和猜测,比如字符之间的空格间隔应该是多少。

      这在很大程度上还取决于制作 PDF 的软件,这些软件会使提取文本变得更容易或更困难。

      1. 我最喜欢的是他们通过复制和稍微移动字母来做粗体。Bboolldd。PDF 简直是地狱。

        1. 这是从最初的机器便携式文档格式–打字机说明书–继承下来的。

      2. 我从未研究过 PDF 格式,但它不允许注释说 “矩形((x0, y0), (x1, y1)) 中的字形代表文本‘foobar’”吗?) 这就是我对它们如何进行文本搜索的思维模式。

    2. PDF 本身支持可选择/可提取文本。ISO 32000 第 9.10 节就是 “提取文本内容”。我自己就在生产软件中实现了这一点。

      PDF 采用 “渲染字形 ”指令而不是 “渲染字符串 ”指令有很多很好的理由。尤其是您的打印机和 PDF 阅读器不需要使用相同的文本形状和布局算法,就能使 PDF 呈现出相同的效果。哎呀,你的打印机运行的是不同版本的 Harfbuzz!

      兄弟姐妹的评论是对的,这在很大程度上取决于制作 PDF 的软件。重要的是要准确判断责任所在。当电子应用程序使用过多内存时,我不会责怪 x86 ISA 或 C++ 标准委员会。

    3. 这是由于在实现 pdfTeX 时做出的错误选择。例如,TeX 引擎不会将原始空格字符与取代它们的字间距 “胶水 ”联系起来,因此 pdfTeX 很乐意省略它们。几年前,这个问题终于得到了解决。但还有数百万(?)篇论文没有空格。

    4. fi fl ffi ffl 等连字符是为了在屏幕或打印机上正确显示而对字体进行的特定更改。其目的是渲染格式,而不是可解析格式。

      格式化良好的电子书和 HTML 通常是为了适应最终用户的需求,更好地适应可用的版面空间。

      1. 虽然这也是一种陷入困境的传统回溯。现代的建议是,不要直接向渲染器发送连字,而是让渲染器使用 OpenType 功能(和 Unicode/ICU 算法)自行构建连字。PDF 在其文件中使用了一些连字符号,这似乎是一种向后兼容的传统错误,因为它仍然支持古老的 “哑巴 ”PostScript 字体和前 Unicode 字体编码(或至少是前 Unicode 规范化格式)。这也与 PDF 一直搞不清楚自己是否是堆栈中的最终呈现器有关。

        1. 这对于 PDF 作为任意纸张类格式的用例来说是行不通的,因为各种 Unicode 和 OpenType 算法并没有为呈现任意文本提供足够的功能:没有放之四海而皆准的规则!这些标准是一套通用的 “尽最大努力 ”准则,用于最低通用标准的文本排版,而且还在不断扩展。

          即使对英语来说,精确调整换行和连字符也是一个不时需要人工干预的问题。在数学研究论文中,经常可以看到一些还未被纳入 Unicode 的符号。看看网络上的文本状况,你就会发现所有这些问题;甚至 Google Docs 也让步了,现在可以渲染到画布上。

          PDF 的 Unicode 处理确实是一团糟,但它确实有能力将任何字形与任意 Unicode 字符串关联起来,以便进行文本提取,因此没有什么能阻止生成 PDF 的程序将 fi 结尾字形映射为字符串 “fi”。

          1. 我认为你在这里看到的问题与我抱怨的问题不同。也许我可以重述一下: 基线 PDF 1.0 类似于(但不完全是)渲染打印到特定的 PostScript 打印机,它能理解嵌入式 PostScript 字体,有点像但不完全是早期 Apple LaserWriter 的虚拟版本。多年来,PDF 的版本不断扩展,包括扩展和升级,现在 PDF 所代表的目标 “打印机 ”已经升级,也能在 PostScript 中理解 Unicode,还能理解嵌入式 OpenType 字体(及其字符映射、连字符和上下文交替等许多扩展)。但是,由于传统的打印机比较笨,只能实现最简单的 “向后兼容”,所以很多 PDF 渲染应用程序仍然在做一些蠢事,比如 “手工 ”编码连字符,如一些扩展的 ASCII 码页或预先组合的 Unicode 形式,而这些形式如今已被我们认为是过时的,就好像它们是打印到 PostScript 打印机上一样,而 PostScript 打印机由于仍然只能打印较旧的 PostScript 字体,所以无法直接理解连字符。

            是的,如果不在 PDF 中嵌入字体(或至少是字体的度量标准),PDF 排版的确定性就会降低,字体之间也会发生变化。问题的关键在于,我们可以在 PDF 中嵌入现代字体,虚拟打印机也为此升级了支持,但由于种种原因,一些构建 PDF 的工具仍在按照最低公分母进行 “打印”,并在 2024 年使用传统的 EBCDIC 连字符编码。(有趣的事实是:Unicode 的连接编码嵌入与一些经典的 EBCDIC 报告打印代码页相比,更接近于 Extended ASCII 的等效代码页,因为存在着更大的向后兼容性鸿沟)。

      2. 这很好,但一个好的编译格式还应该包括一个源代码图,以便于访问。

    5. 很遗憾,CSS 分页仍然是一团糟。我并不喜欢 CSS,但它能大大帮助我们从 PDF 中解锁一些布局。

      1. 同意–几年前我曾用 CSS 来排版一本书,效果还不错,但那些支持不佳或根本不起作用的东西(如页码)就很麻烦了。

    6. XPS 解决了 PDF 的许多问题,但微软的采用率还没有达到让网络效应占据上风的临界水平。

      不过,我不知道 XPS 是否能更好地处理文本复制。

    7. 如果 PDF 不支持文本提取,那就是创建 PDF 的软件的问题。很可能是软件没有在 PDF 中包含字形 → Unicode 字符映射。

  4. 以前提交的论文本身:

    https://news.ycombinator.com/item?id=41321876 (第一次) https://news.ycombinator.com/item?id=41338877 (大量讨论)

    我尝试了这种新语法,对于复杂的分析查询来说,这似乎是一个合理的建议。不过这种新语法可能不会改变大多数简单的事务查询。该语法与执行语义更加匹配,这意味着用户不太可能需要以奇怪的形式提出查询,才能使查询规划器按预期工作;通常用户只需要将一些管道操作符移到更合适的位置。

    1. 有点像 PRQL 的半成品。比如说,如果我们要使用非标准 sql,那就修复一大堆问题,而不是只修复一两个?

      1. > 比如,如果我们要使用非标准 sql,那就解决一大堆问题,而不是一两个?

        我认为他们是有意避免对语言进行大规模的重新设计,因为这很有可能导致几十年来令人沮丧的死亡进程。我从 C++ 标准提案中了解到一些这样的情况,可能开发团队就是想避免这种情况。

      2. 论文中提到了这一点–能在现有 SQL 语言中进行部署是件好事,而且也不排除使用 PRQL 的可能性

      3. > 有点像 PRQL 的半成品。比如说,如果我们要使用非标准 sql,那就解决一大堆问题,而不是只解决一两个?

        老实说,这和 IPv6 所犯的错误如出一辙。它不仅仅是 “让我们扩展 IPv4 地址空间,并提供一个尽可能渐进的升级路径”,而是 “IPv4 存在所有这些问题,让我们用一个全新的地址空间来解决地址空间问题,同时我们还要解决其他 20 个问题!” 与此同时,四分之一个世纪过去了,IPv4 仍然没有很快消失的迹象。

        比起 “为了新的涅槃,我们把所有旧的东西都扔掉吧!”这种做法,我更愿意采用渐进式改进,解决我 90% 的痛点。我是一个非常喜欢 PRQL 的人。

        1. 在保持兼容性的同时,你不能 “仅仅 ”扩展 IPv4 地址空间。

          1. 在当前的 IPv4 协议标头中扩展 src/dst 要比采用全新的套件容易得多。

            1. > 扩展当前 IPv4 协议标头中的 src/dst 比采用全新的套件要容易得多。

              而这也正是当时竞争提案之一的原因,所以这告诉我,仅仅简单可能还不够。

              您可以搜索 RFC 1475(“IPv7”)及其相关历史。

              1. 是的,我知道。IPv6 之所以获胜,是因为它客观上是一个更优越的标准。当然,没有政治因素,全是委员会的垃圾。

      1. 谢谢,我已将其添加到我的评论中。我错过了所有的讨论!

  5. 每次出现这种 FROM 优先的语法风格时,总是最基本的简单查询(一个表,没有投影/子选择/对 SP/Views 的考虑)。

    就这一次,我想马上看到在实际高级查询中使用该语法的完整示例。当然,可以抛出一个简单的案例,但请告诉我,当我必须将 4-5 个参考表连接到一个事实表,然后根据这些内容进行筛选时,它是什么样子的。

    一旦你这样做了,就会明白为什么 SELECT 最先胜出:易读性和故障排除。

    只要数据库继续支持标准 SQL,他们就可以添加任何额外的语法支持,但根据历史经验,这最终会成为新一代 emacs vs vi 风格的圣战。

    1. 听起来有点像 “吓人的新东西”,除非你能说明为什么把 select 放在前面能避免问题,我不认为它们能避免什么明显的问题,但它确实让自动完成变得非常困难(你能正确完成吗?

      1. > 听起来有点像 “新东西吓人”,除非你能说明为什么把 select 放在前面实际上可以避免问题。

        这并不公平。BeefWellington 给出了 SQL 为何如此的原因(50 年来一直如此)。要求给出改变子句顺序的令人信服的理由是合理的。Simon 的帖子说 “一直以来都很混乱”,但并没有真正解释原因,只是链接到一篇博文,说 SQL 引擎(算是,但不是真的)以不同的顺序执行子句。

        我认为,证明 SQL 语句顺序错误的举证责任在于声称它们顺序错误的人。

        1. 但这已经从很多角度解释过很多次了。

          * SELECT 优先会使自动完成变得困难

          * 从执行的角度来看,SELECT first 是 SQL 语句中唯一一个顺序不对的子句

          * 不能在下面的子句中使用 SELECT 中定义的别名

          * 在某些地方 SELECT 是没有意义的,但它仍然是必需的(保持一致性?)

          可能还有更多。

          1. > 不能在以下子句中使用 SELECT 中定义的别名

            有些数据库允许或部分允许这样做。对我来说,在不同的数据库系统中进行猜测工作是一个主要的经常性摩擦因素。

      2. 在这种情况下,陈述你的观点和资历会让你听起来非常老成和保守,因此很容易被人利用,比如 “你只是害怕改变”。

        在我之前的工作中,我为一个应用程序工作了十年,这意味着要创建和维护大型的毛茸茸的 sql,这些 sql 是为了将应用程序逻辑卸载到数据库而创建的(非常原始),我们经常谈论这种 “错误的顺序”,但我从来没有真正错过它。当你跳转到服务器上排除故障时,如果你知道你感兴趣的两列,你就可以节省两秒钟的时间,这最多是有点恼人。但在维护大型查询时,将投影放在最上面总是感觉很好,因为这是最终结果,也是查询的目的所在。如果 Java 方法签名中只有参数,而返回类型在最后一个括号之后,我就不会喜欢了。当然,这个类比是不成立的,因为参数到处都是,但交换一下也无济于事。

        因此,只需输入 “SELECT *…”,稍后再返回并展开,我希望我的 sql 语法 “简单”。/老开发人员

      3. 其实不然。我在这一领域工作了很长时间,其中很多年都在做 DBA 和数据建模师。我也用过其他语法,主要是 MDX,但也用过一些 Hadoop/Spark 特有的语法。我并不害怕新事物。我只是希望他们能在我们现有的基础上加以改进。我希望他们能坦诚面对自己的解决方案并不出色的情况。

        SQL 有很多缺点,例如:你可以编写连接表的 SQL,而不将这些表包含在 JOIN 中,这会导致混乱。它也很零散–我发布的另一个示例显示了 TOP N / LIMIT N 的两种不同语法,这是因为不同的供应商采用了不同的方法。事实上,有些 RDBMS 提供锁定提示机制,有些则不提供(至少不可靠)。没有在任何地方定义一套标准的 “库 ”函数,因此在数据库之间移植需要大量的验证工作。这使得移植变得很困难,而标准中又缺少其中的一些功能。

        你会注意到,我还提到,如果他们想添加这些功能,那也没问题,但这在很多地方都会成为争论的焦点。这是因为我看到过 “大数据 ”与 “我们现有的功能 ”之间也发生过同样的事情。

        事先进行选择可以从几个关键方面避免问题:

        1. 正在开发应用程序的开发人员可以立即看到结果集中有哪些字段。对于 CRUD,通常可能只是他们选择的字段或 `*`,因为每个人都习惯于询问他们永远用不到的每个字段。

        2. 排除故障要容易得多,因为问题几乎总是源于预测中的某个字段。查看投影字段列表(以及该字段来自的表别名)是开始排除故障所需的第一条信息(是哪个字段以及该字段来自哪里)。这就是为什么 SELECT … FROM 最有意义的原因–它直接提供了两个最关键的信息。

        3. 无论如何,查询规划者已经优化并编译了整个查询过程,因此在我看来,可读性比其他选项更重要。

        还有一点我想对你和其他提到自动完成的人说: 如果你需要,没有什么能阻止你先写 FROM 子句,然后再往上一行写 SELECT。这有点像你先写出函数定义,然后再添加参数。这不会影响最终表格的可读性。

    2. > SELECT 最初胜出的原因变得清晰了:易读性和故障排除

      没有什么 “变得清晰 ”是你自己说的,最好详细说明一下

    3. > 一旦你这样做了,就会明白为什么 SELECT first 最初会胜出:易读性和故障排除。

      对于早期的 SQL 设计者来说,“Select first ”就像 “它听起来更像一个英语句子 ”一样偶然。另外,他们当时使用的是早期的解析器,前瞻性非常有限,把主要 “动词 ”放在前面在当时非常重要。

      但英语是非常灵活的,尤其是在 “命令语法 ”中,From first(从头开始)的用法非常普遍:“From the middle cupboard, grab a plate”(从中间的柜子里拿一个盘子)。SQL 试图在这里听起来像英语,这只能说明它与真正的英语相比仍然不够灵活。

      自从 2007 年 C# 的 LINQ 被添加到语言中后,我就一直在使用它,from/where/join/group by/select 的顺序感觉非常好,非常易读,尤其是因为它提供了很好的自动完成支持,而且故障排除比人们想象的要容易得多。

    4. https://prql-lang.org/ 主页上有很多很好的示例。

      如果你使用系统 2 思维(前额叶皮层,速度慢,我们天生懒于使用的思维部分)而不是系统 1(自动化、本能、优化的大脑路径,我们习惯于使用的东西)来处理语法,你很可能会发现它更简单、更有逻辑意义,这样你就能像筛子一样自然地过滤掉一些东西,而且随着复杂性的增加,它比 SQL 的编译效果要好得多。

      在你将其内化之后,想象一下我们可以在这种逻辑结构之上构建什么样的开发人员工具。

      1. > 如果你使用系统 2 思维(前额叶皮层,速度慢,我们天生懒于使用的思维部分)而不是系统 1(自动化、本能、优化的大脑路径,我们习惯于使用的东西)来处理语法

        也许你本意并非如此,但你选择的措辞非常居高临下。

        1. 我重新读了一遍,我知道有些人可能会这么认为,谢谢你的指出。也许有更好的措辞或添加更多的上下文可以让它更友好:

          我们的目的是明确告诉人们,除非某些东西特别能引起我们的兴趣,否则不要费心去 “只读它”(我指的是我自己和我认识的大多数人,当然也有例外)。

          如果没有积极的、有意识的努力,与我们习惯的语法不同的语法(特别是像 SQL 这样成熟的语法),乍一看并没有突破性的变化,很容易让我们不以为然,而没有意识到它的好处。在经历了太多次各种技术的 “离经叛道 ”之后,我只想让读者做好心理准备,这样他们在做出判断时才能充分发挥自己的能力,而不是做出条件反射式的反应。

      2. 编辑:今早喝咖啡前的匆忙中,我完全忽略了按角色分组(其实也没那么难)。不幸的是,这使我发布的整个帖子失效,我不想传播错误信息。

        1. 我不认为你的替代方案能解决相同的问题。你的替代方案只能提供最近加入的单个员工。实际要解决的问题是找到每个角色中最近加入的员工。

          你需要进行一些分组,才能从整个数据集中找到每个角色中的一名员工,而不是一名员工。

          1. 是的,你说得对,我注意到了这一点,并在你回复时编辑了我的回复。

            如果时间允许,我将在更新的回复中提供修正过的 SQL。

    5. 作为测试,我重构了一个 500 行左右的分析查询,它连接了 20 多个表和几十个复杂的 CTE,我可以说,这种 FROM 优先语法几乎在所有方面都优于传统语法。

    6. > SELECT 优先最初的优势在于:易读性和故障排除。

      深入研究 70x/80x 时代 SQL 替代语法的历史是非常有趣的。

    7. > 一旦你这样做了,就会明白为什么 SELECT 最初会胜出:易读性和故障排除。

      此外,工具可以通过遇到的第一个单词区分 DQL 和 DML,数据修改函数除外(天哪,不!)。

    8. FROM 顺序是 SQL 中最不令人反感和最不错误的地方。

      卓越的 “自行车”。

  6. 标题或许应该改一下,因为这篇文章是关于使用人工智能将 PDF 转换为语义 HTML 的。

    1. 在维护链接博客的过程中,我发现了一个令人吃惊的问题,那就是博客中的文章偶尔会被提交到 Hacker News 上,而 Hacker News 上的人不可避免地会指责这些文章与链接来源不符–这很公平!这就是为什么我自己不提交这些文章的原因。

      这篇特别的文章很快就变成了我抱怨 PDF,然后演示双子座专业版技巧的一个非常隐蔽的借口。

      在这种情况下,我转换成了 HTML 格式–后来我又试着把论文转换成 Markdown 格式,然后在 Gist 中分享,我觉得效果更好:

      https://gist.github.com/simonw/46a33d66e069efe5c10b63625fdab… – 此处注释 https://simonwillison.net/2024/Aug/27/distro/

        1. 很不错!我喜欢它也是由 GitHub 员工运营的(可能是作为一个副项目,但仍然是)–这让我不那么担心域名有一天会消失。

  7. 这让我想起了.NET 短暂的 Linq to SQL;

    当时有一个演讲,但我找不到视频了:http://jaoo.dk/aarhus2007/presentation/Using+LINQ+to+SQL+to+….

    基本上,这是一种将 SQL 查询干净利落地插入 C# 代码的方法。

    它使用了这种排序方式(约束在被约束的内容之后);IntelliSense 需要这样做才能工作。

    1. “昙花一现”?LINQ 在 C# 生态系统中的生命力很强。

      无论自动完成与否,FROM-first 语法绝对更有意义。一般来说,你应该把 “我需要选择什么 ”放在 “我从什么中选择 ”之后。

      1. LINQ 是的,但他们在推出该组件后不久就将其扼杀了。

    2. > 这让我想起了.NET中昙花一现的Linq to SQL;

      “昙花一现”?从目前的情况看,它还活着,而针对相同用例的更流行的新产品 Linq to Enntities 具有相同的显著特点,但(因为它与 Entity Framework 绑定,而非 SQL Server 专用)可用性更广。

        1. 是的。Linq to sql 是一个比 EF 更轻量级的扩展,由于 MS 的内部争斗而被扼杀。

          数据库人员投入了大量的时间和精力来 “正确 ”地使用 EF,而 Linq to sql 这个小巧实用的工具却被视为竞争对手。

          1. 在它存在的 5 分钟里,我非常喜欢它–它真的非常容易使用。

        2. LINQ 与 LINQ-to-SQL 不同。前者是一种语言特性,后者是使用该特性的库(众多库之一)。

          1. 你是不是回错人了?因为我不是不知道这一点的人。

          2. 是的,我非常喜欢阅读排版固定的 PDF 文档,而不是 HTML 或任何其他格式的文本,包括在小手机屏幕上。

            我经常阅读多达数千页的文件,其中还包含许多图表。

            可变版式,至少对我来说,会使浏览和搜索这些文件变得更加困难。

            我从未见过让文本回流与临时用来显示文本的窗口相匹配有什么好处,除非是那些我再也不会阅读的短暂信息。

            对于任何我将多次阅读的内容,我都希望文本能保持相同的布局,无论在什么设备或窗口上显示。如果有必要,我认为调整窗口以适应文本是没有问题的,而不是允许文本发生变化,因为这会影响我从以前的阅读中记忆文本的能力。

            我真的很讨厌那些不以 PDF 文档形式提供技术文档的人,他们只满足于提供一些网页。

          3. 我不希望为了适应屏幕而重新书写文本。文本每行的最佳字符数在 40 到 60 之间,这取决于你问谁。行数超过这个数字会妨碍阅读。比这更短的行则会造成不便。

            通常采用双栏布局是因为单栏每行 40 至 60 个字符会浪费纸张。这确实是个问题。但解决办法是让 PDF 页面更窄。无论如何,几乎没有人会打印这些文档;没有充分的理由需要它们符合传统的尺寸,如办公室打印机中常见的 A4 或 Letter 纸张。选择 A5 作为尺寸即可。真正需要打印的人可以在一页 A4 纸上放两页 A5 纸,而在手机屏幕上查看这些文档的人也会觉得 A5 纸更方便。

  8. 我使用的第一种管道式查询语言是 Nushell 的宽列表实现。PRQL 提供了几乎类似的方法,让我爱不释手。它还可以映射到不同的 SQL 方言。还有人建议在类型系统上下功夫:https://github.com/PRQL/prql/issues/381。

    现在,Google 从这些方法中获得灵感,提出了一种语法。不过,我担心它的采用率会有多高。作为 SQL 的新手,几乎每个数据库都提供了自己的 SQL 方言,这很快就会变得繁琐。

    而 PRQL 给人的感觉就像 Apache Arrow,可以映射到其他方言。

  9. 至于作者对网络上的 PDF 所提出的问题:PDF 并非用于在手机上查看反应式网络应用程序。并非所有东西都必须如此。如果你真的需要阅读研究论文,那就找个大于 3 英寸宽的屏幕吧。

    1. 我认为他的观点是,谷歌是一家网络公司。也是一家手机公司。而且他们发布的很多东西的格式基本上都是为打印而优化的,对其他任何东西都没什么用。

      我在 20 多年前攻读博士学位,当时处理所有这些 postscript 和 pdf 文档是一件很烦人的事。现在也一样。如今,人们在网站上以 PDF 格式发布内容,而大多不在印刷媒体上发布。人们可能会打印,也可能不会。二十年前,我肯定会打印。但奇怪的是,我们还是坚持这样做。当然,PDF 格式的内容很不结构化,也很难通过编程来理解。

      我敢打赌,现代很多科学家都不再打印他们阅读的文章,而是在屏幕上阅读,或者在 iPad 或电子阅读器上阅读。打印已经成为一种边缘情况。在小型电子阅读器上阅读 pdf 并不理想。任何带列的内容都很难处理。大多数网站不使用分栏也是有原因的:从用户体验的角度看,这有点糟糕。传递文本的最佳形式是响应式,可以适应任何屏幕尺寸,还可以改变字体大小。很多科学论文的布局都经过了优化,以节省一种不再重要的资源:纸张面积。小字体、多列等。

      总之,我喜欢西蒙的解决方案和它的工作原理。有趣的是,有些 LLM 居然如此懒惰。参考文献被省略的事情很搞笑。我在聊天 Gpt 上也看到了同样的情况,它从来不会完全按照你的要求去做,而只是给你一些你要求的零碎内容,直到你求它请 FFing 按你说的去做?我猜他们是想节省一些代币或 GPU 时间。

    2. 为什么我不能在手机上阅读研究论文?我几乎所有其他东西都是在手机上看的。

      1. 即使是在手机上阅读,我也不理解对两栏格式的抱怨。

        单栏格式在大显示器上还不错,但在小手机上,我更喜欢窄栏,因为宽栏要么会使文字太小,要么阅读时需要水平平移。

        因此,我认为双栏格式更适合手机,而不是更糟。

  10. 我实际上在 SQL Server 上工作,但我也写了很多 KQL 查询,它们也是这样工作的,我完全同意顺序管道的东西更容易写。我还没有通读整篇论文,但我非常喜欢的一点是,我认为用这种顺序方式指导查询优化更容易。

    1. SQL 服务器的这种变化是否存在内部惯性?

      1. 考虑到 Entity Framework 作为 SQL Server 的 “首选 ORM ”无处不在,以及它对 C# Linq 的使用,无论 SQL Server 开发人员本身是否关注大多数用户如今是如何编写查询的,外部动力肯定是存在的。

  11. 我写 SQL 大概有 25 年了,一直认为被 SELECT 的列应该放在最后,而不是第一位。至少在我看来,在试图从中获取什么之前先命名数据源更符合逻辑。在别名之前调用别名的表名是很奇怪的。

    此外,这还能让智能集成开发环境中的自动完成功能在输入查询时更有帮助。

    1. 我也是这么想的。示例查询看起来很像 Ecto 语句。当我在其他平台上使用数据库封装器时,我很怀念 Ecto 的人机工程学和灵活性。

  12. 接下来,我想定义一个包含大量|>项的函数/宏。

    我指出,你可以用 shell 来做到这一点:

    管道支持矢量化、无点和执行式 https://www.oilshell.org/blog/2017/01/15.html

    e.g.

        hist() {
          sort | uniq -c | sort -n -r
        }
        $ { echo a; echo bb; echo a; } | hist
          1 bb
          2 a
        $ foo | hist
        ...
       
    

    SQL 中应该可以实现类似功能!

      1. 很好,谢谢!

        那么标量值函数呢?) 这样我就可以在 WHERE 中重复使用一个表达式,等等。

        (我很欣赏 HAVING 可以被泛化/删除)

  13. 我第一次没看到这个:

     GROUP AND ORDER BY component_id DESC;
    

    除了管道操作符之外,这种结合分组和排序的语法真的有必要吗?我的建议是添加管道运算符,而不是花里胡哨地在 SQL 中添加其他语法。

    1. 这可能是论文中泄露的自定义 zetasql 扩展。

  14. 这基本上就是带有 tidyverse 的 R。

      flights |>
        filter(
          carrier == "UA",
          dest %in% c("IAH", "HOU"),
          sched_dep_time > 0900,
          sched_arr_time < 2000
          ) |>
        group_by(flight) |>
        summarize(
          delay = mean(arr_delay, na.rm = TRUE),
          cancelled = sum(is.na(arr_delay)),
          n = n()
          ) |>
        filter(n > 10)
    

    如果你还没有使用过 R,它内置了一些重要的数据处理功能。

    1. 对于所有这些 dplyr 风格的语法,我觉得有趣的一点是,Wickham 认为 group_by 操作符是一个设计错误。在现代的 dplyr 中,你通常可以指定一个 .by 来代替操作。我发现切换到这种风格很容易调整,而且我认为这样更好一些。例如

       d |> filter(id==max(id),.by=orderId)
      

      我认为 PRQL 正在考虑如何避免使用 group_by 操作,我认为他们使用的是一种 “范围 ”或 “高阶 ”group_by 操作,它使用分组键和管道,并输出一个管道步骤,将内部管道应用于每个分组。

      1. 再过十年,dplyr 的语法可能会类似于 data.table 的

    2. 我也是这么想的,它甚至使用了相同的管道语法,不过我更喜欢 `%>%`。我已经回避 SQL 有一段时间了,因为与 tidyverse 相比,它给人的感觉太笨拙了。

      1. 需要牢记的关键一点是,鸫鸟组合器只是一个简单结构的花哨名称。它提供的语义是传统函数组合的声明形式。

        例如,给定表达式

         f (g (h (x)))
        

        同样的表达式在支持“|>”下位运算符的语言中可以表示为

         h (x) |> g |> f
        

        还有其他等价的构造,例如 Scala 中的 Cats Arrow[0] 类型类、Haskell 中相同的 Arrow[1] 概念,以及许多现代编程语言中常用的 `andThen` 方法。

        0 – https://typelevel.org/cats/typeclasses/arrow.html

        1 – https://wiki.haskell.org/Arrow_tutorial

  15. 我们真的应该将 SQL 的核心语言标准化。Rust 有 MIR,Clang 正在为 C/C++ 制作 CIR。一旦有了这些,我们就能更好地交流。

    现在,每个人都在使用不同的心理模型和难看的单程编译器(据我所知,在大多数数据库中,解析–>查询规划的分离程度远不如大多数编译器中的解析–>优化–>代码生成)。

    1. > 我们真的应该将 SQL 的核心语言标准化

      你是指 ISO/IEC 9075:2023(第 9 版 SQL 标准)之外的语言吗?

      1. 阅读需要 194 瑞士法郎。还有改进的余地。

      2. 核心语言是一种没有表层语法的最小 AST(因此不需要对表层语法进行分拆),它将表层语言提炼为其本质。

        1. SQL 基本上是 list monad,有各种商/细化:

          – 有时顺序并不重要 – 有时存在功能依赖 – 有时人们知道相关列表的长度为 1(外键约束)

    2. ANSI SQL 是一个非常重要的东西,如果你希望这些查询将来可以移植到其他数据库技术中,那么你就应该在数据库引擎允许的范围内,努力使你的查询尽可能接近标准 SQL。

  16. 研究论文:https://storage.googleapis.com/gweb-research2023-media/pubto…

  17. 我只想让拖尾逗号无处不在。真不敢相信,都 2024 年了,我们还得面对这些垃圾。人类应该得到更好的。

    语法/DSL 设计者们:如果你们的语言使用分隔符,请尽可能允许分隔符的拖尾版本。

  18. 我对 SQL 最大的愿望就是单行插入能有 {key: value} 语法。

    1. 在 ClickHouse 中,您可以使用

       INSERT INTO table FORMAT JSONEachRow {“key”: 123}
      

      它也适用于所有其他格式。

      此外,它的设计方式使您可以进行 INSERT 查询和数据流,例如

          clickhouse-client --query "INSERT INTO table FORMAT Protobuf" < data.protobuf
          curl 'https://example.com/?query=INSERT...' --data-binary @- < data.bson
    2. 这将大大减少代码行数,并防止出现许多愚蠢的 bug。

  19. 我觉得这种特殊的语法选择有些有趣,因为基于管道符号的查询结构是我一年前在用 OCaml 制作 SQL 库时最终使用的:

    https://github.com/kiranandcode/petrol

    查询示例如下

    “`

    let insert_person ~name:n ~age:a db = Query.insert ~table:example_table ~values:Expr.[ name := s n; age := i a ] |> Request.make_zero |> Petrol.exec db

    “`

  20. 感觉这应该被写入官方 SQL 标准,并被大量 RDBMS 支持,同时被 IDE、库和框架所理解。

    1. 是的,鉴于现有语法的流行性,我们将有两个标准

  21. 请看 PDF 中的第一个示例:

        FROM customer
        |> LEFT OUTER JOIN orders ON c_custkey = o_custkey
        AND o_comment NOT LIKE '%unusual%packages%'
        |> AGGREGATE COUNT(o_orderkey) c_count
        GROUP BY c_custkey
        |> AGGREGATE COUNT(*) AS custdist
        GROUP BY c_count
        |> ORDER BY custdist DESC, c_count DESC;
    

    您可以使用 Ryelang 的电子表格数据类型做类似的事情:

        customers: loadcsv %customers.csv
        orders: loadcsv %orders.csv
        orders .where-not-contains 'o_comment "unusual packages" 
        |left-join customers 'o_custkey 'c_custkey
        |group-by 'c_custkey { 'c_custkey count }
        |group-by 'c_custkey_count { 'c_custkey_count count }
        |order-by 'c_custkey_count_count 'descending
    

    考虑到这一点,也许我们应该在分组功能中添加一个选项来命名新的聚合列(现在它们会自动命名),因为例如 c_custkey_count_count 并不那么优雅。

  22. 是否有研究表明,在筛选许多查询时,什么更容易阅读?

    我喜欢先读取语句期望输出的内容的语法,尽管我同意我不会先写 select。我觉得这可能优化错了。

    虽然示例很好,但它没有显示先连接的 20 个表,这确实会让人一头雾水。

    1. 如果没有后面的内容,选择列表就毫无意义。如果不知道表和搜索条件等,只知道查询选择了 “id, ”date”,就什么都不知道。

      1. 这就是 SQL 命名约定的一个好处,它可以使用诸如 customer_id、invoice_date 等名称。此外,在连接表时(取决于 SQL 方言),如果两个表中的字段名相同,可以使用快捷方式 synax、JOIN ON field_name。

      2. 我真希望 SQL 使用 “RETURN ”而不是 “SELECT”(如 XQuery):

        1. 称其为 “RETURN ”会使其较后的执行顺序(相对于 FROM 等)不那么令人惊讶。

        2. “RETURN RAND() “比 ”SELECT RAND() “读起来更自然。毕竟,我们在这里并没有真正 “选择 ”任何东西,不是吗?

        3. 还能消除与关系代数中的选择操作的混淆。

      3. 如果以这种方式命名字段,但 accountId、createDate 在您查看的上下文中可能并非毫无意义。

  23. Clojure 中有一个 honeysql 库,可以将查询定义为映射,然后将映射渲染为 SQL 字符串:

     {:select [:name :age] :from {:people :p}
         :from {:people :p}
         where [:> :age 10]}
    

    由于映射是无序的,因此等价于

     {:from {:people :p}
         :select [:name :age] :where [:> :age 10
         :where [:> :age 10]}
    

    以及

     {:where [:> :age 10]
         :select [:name :age]
         :from {:people :p}}
    

    这些内容都可以呈现为 “SELECT… FROM “或 ”FROM … SELECT”。

    作为数据结构的查询用途非常广泛,因为你可以使用语言结构来组成它们。

    而作为字符串的查询(无论是否 FROM 优先)仍然是字符串,很难在不破坏语法的情况下进行组合。

  24. > GROUP AND ORDER BY component_id DESC;

    这感觉太多了。GROUP BY 和 ORDER BY 是两个独立的子句,在一个子句中对它们进行分组(呵呵)会使认知负荷复杂化,尤其是在努力减少在头脑中解析查询的总体工作量(并为类似智能感知的系统提供更好的建议)的情况下。

     GROUP AND ORDER BY x DESC;
    

     GROUP BY x;
        ORDER BY x DESC;
    

    这种长表单虽然长了 1 个字,但更容易在头脑中解析,而且在更改 GROUP 或 ORDER BY 列引用时不会引入不必要的差异。

  25. 我喜欢这个想法,但一看到管道运算符,我的大脑就开始发痒

     |>
    

    那是什么东西?Unix 管道和重定向搞混了?一只戴着墨镜的鸟的奇怪笑脸?

    对我来说,这需要一些时间来适应……

    1. 这就像当今常用编程语言中的其他 “箭头 ”数字,如 =>。你可以把它想象成一个指向右边的三角形。

      许多编程字符字体甚至经常这样画它。例如,在 Fira Code README 中的 F# 下就有这样的显示:https://github.com/tonsky/FiraCode

    2. 他们考虑过放弃 `|>` 或使用 `|`,但不幸的是,这样会产生一堆语法歧义。

  26. > 理由: 我们为全表聚合和分组聚合使用了相同的操作符名称,以尽量减少这些操作之间的编辑距离。遗憾的是,这使得分组和聚合列在语法和输出中的顺序不同。如果将 GROUP BY 放在前面,就需要在 AGGREGATE 列表前添加一个必填关键字。

    我认为这是错误的。让列按顺序排列比全表聚合的语法更重要。

  27. 为什么还要添加管道运算符?

    如果 DB 引擎在执行语句时顺序不对,为什么不允许以任何顺序写入语句,而是让它自己解决呢?

    1. 在一般情况下,聚合可能是非交换性的,因此顺序很重要。分组前后的过滤器也与管道中的特定位置有关。

    2. > 为什么还要添加管道运算符?

      让人类更容易读/写查询。

  28. 我还没看到有人提到它,但它让我想起了 PQL(不是 PRQL):https://pql.dev

    它受到 Kusto 的启发,是一个开源 CLI。在我的一个工具中,它与 SQLite 兼容,使用起来令人耳目一新。

    举个例子:

     StormEvents
      | 其中 State 以 “W ”开头
      | 总结 Count=count() by State

    StormEvents

  29. 对于自动完成来说,FROM 优先是非常合理的。就可读性而言,SELECT 在前更有意义,因为输出总是在顶部。

  30. 这里的人们描述了许多已经拥有类似这种语法和概念的项目,所以我也要把另一种查询语言加进来: Influx 的 Flux 现在已基本废弃。该语言使用相同的 |> 标记,并以等同于 “FROM ”的方式开始结构查询描述。

  31. 如果 DB 引擎在执行语句时顺序不对,为什么不允许以任何顺序写入语句,而是让它自己解决呢?

    1. 在一般情况下,聚合可能是非交换性的,因此顺序很重要。分组前后的过滤器也与管道中的特定位置有关。

    2. > 为什么还要添加管道运算符?
      让人类更容易读/写查询。

  32. 我还没看到有人提到它,但它让我想起了 PQL(不是 PRQL):https://pql.dev
    它受到 Kusto 的启发,是一个开源 CLI。在我的一个工具中,它与 SQLite 兼容,使用起来令人耳目一新。
    举个例子:

      StormEvents
      | where State startswith "W"
      | summarize Count=count() by State
  33. 对于自动完成来说,FROM 优先是非常合理的。就可读性而言,SELECT 在前更有意义,因为输出总是在顶部。

  34. 这里的人们描述了许多已经拥有类似这种语法和概念的项目,所以我也要把另一种查询语言加进来: Influx 的 Flux 现在已基本废弃。该语言使用相同的 |> 标记,并以等同于 “FROM ”的方式开始结构查询描述。

  35. 这就是我喜欢 datastation 和 hex.tech 等工具的原因。使用 SQL 编写初始查询,然后使用 Python/pandas 将结果处理为数据帧。当然,将 Pandas 和 SQL 这样混合使用对于数据管道来说并不好,但对于探索和分析来说,我觉得这种方法很不错。

    1. 是的,在大规模并行商业数据库(Oracle、Snowflake 等)中使用 SQL,然后再在结果集(Pandas 等)中使用 SQL,这是非常方便的。有趣的是,这个概念早在 35 年前的 SAS 中就已经实现了(链接如下),但在今天的 “现代 ”软件中(例如通过 DuckDB),这个概念才刚刚得到普及。

      在 SAS 程序中使用新的 sql 存储过程 (1989) https://support.sas.com/resources/papers/proceedings-archive… Sql 存储过程使用 SQL 从 SAS 数据集和从这些数据集派生的视图中创建、修改和检索数据。您还可以使用 SOL 存储过程,通过 SAS/ACCESS 软件接口将数据集和视图与其他数据库管理系统的数据集和视图连接起来。

      1. 哇,太酷了。我的一个观点是,DuckDB 将被 GCP(BigQuery)收购,而 polars 将被 Databricks(或 AWS)收购。这个观点基于 Snowflake 收购 Modin 平台的想法。数据仓库平台将数据(视图/结果)下传到数据帧(Modin、Polars、DuckDB)平台,然后再将数据下传到它们的商业智能平台。因为这些数据库平台是作为 OLAP 平台设计的,所以这种方法是合理的。

  36. 这只是 C# 中的 Linq,只不过 Google 想把它变成 SQL 标准…

  37. > 已经过去 50 年了。是时候清理 SQL 了。这

    是这样吗?

    我们是要解决人类的 SQL 解析器和生成器问题,还是有一些潜在的实现细节可以从管道中获益?

  38. 手动生成的 SQL 字符串在交互式使用之外还有用武之地吗?我在小型项目中使用它们,但我想知道查询生成器是否更适合大型系统。

    1. 为分析数据库构建查询是不可能的。

      这些查询总是手工滚动的,因为你付钱给分析师来优化它们。

  39. 替换 SQL 就像不了解如此古老的东西成功的程度一样。

    SQL 很好。

    40 年来,SQL 一直是数据库查询的最先进技术。

    等我们都退休了,它还会继续存在。

  40. 他们有点姗姗来迟了,至少有一打这样的流行查询语言。我想到了 LINQ 和 KQL,但还有很多其他的…

  41. 我喜欢这个。让我想起了大熊猫。

  42. 看在上帝的份上,请他妈的别再发明新的管道语言了。

    LINQ: 存在

    Splunk 查询语言:存在

    KQL: 存在

    MongoDB 查询语言:存在

    PRQL:存在

    1. LINQ、Splunk 和 KQL 都是专有语言。就制定新标准而言,它们还不如不存在。

      在为关系查询语言添加流水线语法时,PRQL 是你的列表中唯一真正的参与者,其他人可以在此基础上自由扩展。

    2. SQL 解析器:存在。

      该论文清楚地描述了目标:在现有系统中添加管道语法,只需稍作改动,并与现有 SQL 查询兼容。

      顺便说一句:LINQ 是一种 AST 转换器,而不是一种与特定平台绑定的语言。现有的数据库都不允许直接使用它。

  43. 这不是与 Apache Beam 的语法相同(或非常相似)吗?

  44. 是我的错觉,还是这似乎不合时宜?就像,这是我 20 年前就预料到会发生的对话。迟到总比不到好。

  45. 这读起来就像一个患有精神障碍的人写的文章,他开始写一篇科学论文,但却被一些乱七八糟的东西分散了注意力,而不是去读它。

    1. 见我在这里的评论:https://news.ycombinator.com/item?id=41385143

  46. int *ptr;

    // 但我们还是把它改为 *int ptr;

    // 因为先写指针符号更符合逻辑

    我们能解决一个真正的问题吗?

  47. 等等,这篇文章是关于 SQL 还是 PDF…

  48. 老实说,我喜欢 PDF,它们总是能正常工作,而且不会因为没有 JS 而失败。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注