[FROM x,y]在Postgres中是什么意思?


12

我刚刚开始使用Postgres。阅读此文档时,我遇到了以下查询:

SELECT title, ts_rank_cd(textsearch, query) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE query @@ textsearch
ORDER BY rank DESC
LIMIT 10;

我可以理解此查询中的所有内容,以下内容除外FROM apod, ...

,是什么意思?我习惯于联接,但不能联接多个FROM用逗号分隔的语句。

我在网上搜索无济于事。在查看并思考之后,在我看来,它正在声明一个名为query的变量,因此它可以多次使用。但是,如果这是真的,那又有什么关系FROM呢?

Answers:


10

它创建一个隐式CROSS JOIN。这是SQL-89语法。

在这里,我仅使用values(1)values(2)创建pseduo表(值表)作为示例。在他们之后的事t(x),和g(y)被称为FROM-别名括号内的字符是列(别名xy分别)。您可以轻松地创建一个表来对此进行测试。

SELECT *
FROM (values(1)) AS t(x), (values(2)) AS g(y)

这是您现在编写的方式。

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(2)) AS g(y);

从那里,您可以INNER JOIN通过添加条件来使其隐式。

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(1)) AS g(z)
WHERE x = z;

或显式和更新的INNER JOIN语法,

SELECT *
FROM (values(1)) AS t(x)
INNER JOIN (values(1)) AS g(z)
  ON ( x = z );

因此,在您的示例中。

FROM apod, to_tsquery('neutrino|(dark & matter)') query

这基本上与更新的语法相同,

FROM apod
CROSS JOIN to_tsquery('neutrino|(dark & matter)') AS query

在这种情况下,实际上是相同的,因为to_tsquery()返回一行而不是set,

SELECT title, ts_rank_cd(
  textsearch,
  to_tsquery('neutrino|(dark & matter)')
) AS rank
FROM apod
WHERE to_tsquery('neutrino|(dark & matter)') @@ textsearch
ORDER BY rank DESC
LIMIT 10;

但是,以上内容可能会导致to_tsquery('neutrino|(dark & matter)')发生两次,但是在这种情况下,它不会- to_tsquery被标记为STABLE(已通过验证\dfS+ to_tsquery)。

STABLE表示该函数无法修改数据库,并且在单个表扫描中它将针对相同的参数值一致地返回相同的结果,但其结果可能会在SQL语句之间发生变化。对于其结果取决于数据库查找,参数变量(例如当前时区)等的函数,这是适当的选择。(对于希望查询当前命令修改的行的AFTER触发器来说,这是不合适的。)还请注意, current_timestamp系列功能符合稳定条件,因为它们的值在事务中不会更改。

有关SQL-89和SQL-92之间差异的更完整比较,请参见此处的我的答案


非常感谢你。我只是从SQL开始。进行,交叉连接是有意义的,因为它只是笛卡尔积,并且没有涉及比较。您能再回答1个问题吗?是什么t(x)(values(1)) AS t(x)???
andrerpena

@andrerpena已更新。
埃文·卡罗尔

1
你是最棒的。清晰的解释。万分感谢。
andrerpena

从未听说过表别名的术语“ FROM别名” 。to_tsquery()返回一个不是。仅仅因为定义了一个函数,并不意味着查询计划者避免重复评估。它可以STABLE
Erwin Brandstetter

12

该手册在表格表达式一章FROM列表中详细说明了逗号

FROM子句从逗号分隔的表参考列表中给出的一个或多个其他表中派生出一个表。

FROM table_reference [, table_reference [, ...]]

表引用可以是表名(可能是架构限定的),也可以是派生表,例如子查询,JOIN构造或这些的复杂组合。如果该FROM子句中列出了多个表引用,则这些表是交叉联接的(即,形成了其行的笛卡尔积;请参见下文)。

在SQL标准的早期版本(而不是显式JOIN语法)中定义了逗号分隔的表引用这一事实并不会使逗号错误或过时。在技​​术上有必要(请参阅下文)或使查询文本更清晰的地方,请使用显式联接语法。

再次手册:

FROM T1 CROSS JOIN T2等价于FROM T1 INNER JOIN T2 ON TRUE (见下文)。它也等效于FROM T1, T2

但是“等效” 并不意味着相同。有一个微妙的差异,按照手册笔记

注意
当出现两个以上的表时,后者的等价关系并不完全成立,因为JOIN绑定比逗号更紧密。例如 FROM T1 CROSS JOIN T2 INNER JOIN T3 ON condition,这与 FROM T1, T2 INNER JOIN T3 ON condition因为conditioncan引用T1在第一种情况而不是第二种情况不同。

这个相关问题证明了差异的相关性:

基本上,您的观察完全正确:

在我看来,它声明了一个名为query的变量,因此它可以多次使用。

列表中的任何函数都可以用作“表函数” FROM。并且函数参数可以引用函数左侧所有表中的列,因为符号:

FROM apod, to_tsquery('neutrino|(dark & matter)') query

实际上等于:

FROM apod CROSS JOIN LATERAL to_tsquery('neutrino|(dark & matter)') AS query

有关LATERAL查询的手册:

出现的表函数FROM也可以在关键字之前 LATERAL,但是对于函数而言,关键字是可选的 ; 在任何情况下,函数的参数都可以包含对前面FROM项目提供的列的引用。

大胆强调我的。

关键字AS是完全之前可选噪声表别名(而不是列的别名,它不建议省略AS,以避免可能的歧义)。更多相关答案:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.