首页 > 解决方案 > 使用单个连接子句连接多个表(sqlite)

问题描述

所以我正在学习 SQL(sqlite 风格)并查看sqlite JOIN-clause 文档,我认为这两个语句是有效的:

SELECT *
FROM table1
JOIN (table2, table3) USING (id);
SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id)

(甚至,但这无关紧要:

SELECT *
FROM table1
JOIN (table 2 JOIN table3 USING id) USING id

)

现在我在关于JOIN子句的 SO 问题中看到了很多第二个(链式连接),但很少看到第一个(分组表查询)。对于非简化情况,这两个查询都在 SQLiteStudio 中执行。

此处基于此代码提供了一个最小示例

CREATE TABLE table1 (
    id     INTEGER PRIMARY KEY,
    field1 TEXT
)
WITHOUT ROWID;

CREATE TABLE table2 (
    id     INTEGER PRIMARY KEY,
    field2 TEXT
)
WITHOUT ROWID;

CREATE TABLE table3 (
    id     INTEGER PRIMARY KEY,
    field3 TEXT
)
WITHOUT ROWID;

INSERT INTO table1 (field1, id)
VALUES ('FOO0', 0),
       ('FOO1', 1),
       ('FOO2', 2),
       ('FOO3', 3);

INSERT INTO table2 (field2, id)
VALUES ('BAR0', 0),
       ('BAR2', 1),
       ('BAR3', 3);

INSERT INTO table3 (field3, id)
VALUES ('PIP0', 0),
       ('PIP1', 1),
       ('PIP2', 2);

SELECT *
FROM table1
JOIN (table2, table3) USING (id);

SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id);

有人可以解释为什么一个人会使用一个而不是另一个,如果它们对于某些输入数据不等效,请提供一个例子?第一个对我来说当然看起来更干净(至少不那么多余)。


INNER JOIN ON vs WHERE 子句被建议为可能的重复。虽然它涉及,用作连接运算符,但我觉得问题,尤其是答案更侧重于可读性方面和WHEREvs的使用JOIN。我的问题更多的是关于结果的一般有效性和可能的​​差异(考虑到引起差异的必要输入)。

标签: sqlsqlitejoin

解决方案


SQLite 不强制执行正确的连接语法。它将连接运算符([INNER] JOIN,等,甚至是过时的 1980 年代连接语法的逗号)与条件( , )LEFT [OUTER] JOIN分开。这不好,因为它使连接更容易出错。因此,SQLite 文档对于学习连接来说是一个非常糟糕的参考。(而且 SQLite 本身是一个糟糕的学习系统,因为 DBMS 没有检测到标准的 SQL 连接违规。)ONUSING

坚持 SQL 标准定义的语法(并且永远不要使用逗号分隔的连接):

FROM表 [别名]

((([ INNER ] | [( LEFT | FULL ) [ OUTER ]]) JOIN table [alias] ( ON条件 | USING ( columns ) )) | ( CROSS JOIN table [alias]))

((([ INNER ] | [( LEFT | FULL ) [ OUTER ]]) JOIN table [alias] ( ON条件 | USING ( columns ) )) | ( CROSS JOIN table [alias]))

...

(希望,我做对了 :-) 我也希望这足够可读 :-| 我在这里省略了NATURAL JOINRIGHT [OUTER] JOIN,因为我根本不建议使用它们。)

因为table您可以放置​​一些表名或视图或子查询(后者包括括号,例如(select * from mytable))。中的列USING必须用括号括起来(例如USING (a, b, c))。ON(如果您觉得这更易读,您当然也可以在条件周围使用括号。)

在您的情况下,正确编写的查询将是:

SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id)

或者

SELECT *
FROM table1 t1
JOIN table2 t2 ON t2.id = t1.id
JOIN table3 t3 ON t3.id = t1.id

例如。不过,该示例建议了三个 1:1 相关表。在现实生活中,这些是极其罕见的,一个更典型的例子是

SELECT *
FROM table1 t1
JOIN table2 t2 ON t2.t1_id = t1.id
JOIN table3 t3 ON t3.t2_id = t2.id

推荐阅读