Snowflake (LEFT JOIN) LATERAL:无法评估不支持的子查询类型

Luk*_*zda 6 snowflake-cloud-data-platform

\n

横向连接

\n\n

在 FROM 子句中,LATERAL 关键字允许内联视图引用该内联视图之前的表表达式中的列。

\n\n

横向连接的行为更像是相关子查询,而不是大多数连接。

\n
\n\n

让我们稍微调整一下文档中提供的代码:

\n\n
CREATE TABLE departments (department_id INTEGER, name VARCHAR);\nCREATE TABLE employees (employee_ID INTEGER, last_name VARCHAR,\n                        department_ID INTEGER, project_names ARRAY);\n\nINSERT INTO departments (department_ID, name) VALUES \n    (1, \'Engineering\'), \n    (2, \'Support\'),\n    (3, \'HR\');  -- adding new row\n\nINSERT INTO employees (employee_ID, last_name, department_ID) VALUES \n    (101, \'Richards\', 1),\n    (102, \'Paulson\',  1),\n    (103, \'Johnson\',  2);  \n
Run Code Online (Sandbox Code Playgroud)\n\n

询问:

\n\n
SELECT * \nFROM departments AS d,\nLATERAL (SELECT * FROM employees AS e \n         WHERE e.department_ID = d.department_ID \n         ORDER BY employee_id DESC LIMIT 1) AS iv2  -- adding ORDER BY ... LIMIT ...\nORDER BY employee_ID;\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

SQL编译错误:无法计算不支持的子查询类型

\n
\n\n

是的,我知道我可以用ROW_NUMBER()或其他方式重写此查询。

\n\n
\n\n

TOP/LIMIT1)为什么在这个特定场景中不可能使用?

\n\n

2)有语法可以实现LEFT JOIN LATERAL/OUTER APPLY吗?

\n\n

我也希望能够获取结果集中的所有源行,即使 LATERAL 子查询没有为它们生成任何行。得到最终结果:

\n\n
\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 department_id  \xe2\x94\x82    name      \xe2\x94\x82 employee_id  \xe2\x94\x82 last_name  \xe2\x94\x82 department_id  \xe2\x94\x82 project_names \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82             1  \xe2\x94\x82 Engineering  \xe2\x94\x82 102          \xe2\x94\x82 Paulson    \xe2\x94\x82 1              \xe2\x94\x82 null          \xe2\x94\x82\n\xe2\x94\x82             2  \xe2\x94\x82 Support      \xe2\x94\x82 103          \xe2\x94\x82 Johnson    \xe2\x94\x82 2              \xe2\x94\x82 null          \xe2\x94\x82\n\xe2\x94\x82             3  \xe2\x94\x82 HR           \xe2\x94\x82 null         \xe2\x94\x82 null       \xe2\x94\x82 null           \xe2\x94\x82 null          \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n\n

db<>小提琴演示

\n

Sim*_*rim 3

因此,尽管我们之前讨论过您知道可以重写它,但这里是重写

WITH departments AS (
    SELECT * FROM VALUES
        (1, 'Engineering'), 
        (2, 'Support'),
        (3, 'HR')
        v(department_ID, name)
), employees AS (
    SELECT * FROM VALUES 
        (101, 'Richards', 1),
        (102, 'Paulson',  1),
        (103, 'Johnson',  2)
        v(employee_ID, last_name, department_ID)
), dep_emp AS (
  SELECT * 
  FROM employees 
  QUALIFY ROW_NUMBER() OVER (PARTITION BY department_ID ORDER BY employee_id) = 1
)
SELECT * 
FROM departments AS d
LEFT JOIN dep_emp AS e ON d.department_ID = e.department_ID
ORDER BY employee_ID;
Run Code Online (Sandbox Code Playgroud)

如您所愿给出:

DEPARTMENT_ID    NAME           EMPLOYEE_ID    LAST_NAME    DEPARTMENT_ID
1                Engineering    101            Richards     1
2                Support        103            Johnson      2
3                HR             null           null         null
Run Code Online (Sandbox Code Playgroud)

通过从 LATERAL 转移到带有 QUALIFY 的 CTE 来实现 LIMIT/TOP,然后使用 LEFT JOIN 获取空匹配,您就拥有了所需的步骤。

对于为什么会这样这个未提出的问题。Snowflake 并不是真正的每行数据库,它更像是一个 Map/Reduce/MergeJoin 过程,并且它可以将简单的相关子查询重写为多步骤(也称为 CTE/joins),但它不能重写复杂的东西。他们一直在改进它。但是,如果您了解数据并且了解模型,那么以批量操作来表达事物并让 MergeJoin 的强大功能为您带来胜利是最有意义的。

有没有语法来实现LEFT JOIN LATERAL/OUTER APPLY?这是通过FLATTEN命令, OUTER => TRUE中的参数完成的