T-SQL 中奇怪的 JOIN ON 子句

Jos*_*irk 18 join sql-server t-sql

我正在解开一些遗留代码,而且我多年来从未见过这个:

Select * 

FROM GLAccounts
INNER JOIN GLCharts
    ON glaGLChartID = glcGLChartID
LEFT JOIN GLCategories
    ON glcGLCategoryID = gltGLCategoryID
INNER JOIN GLDepartments
    ON glaGLDepartmentID = gldGLDepartmentID
INNER JOIN GLDivisions
    ON glaGLDivisionID = glvGLDivisionID
        ,GLFiscalYearPeriods                --<this comma>
INNER JOIN GLFiscalYears
    ON glfGLFiscalYearID = glzGLFiscalYearID


ORDER BY glcGLCategoryID
    ,glcParentGLChartID
    ,glaGLChartID
Run Code Online (Sandbox Code Playgroud)

连接有效,但我没有在 ON 子句的任何 T-SQL 语法参考中找到逗号的这种用法。

这里发生了什么事?TIA

McN*_*ets 20

GLFiscalYearPeriods 是一个表,这个逗号意味着交叉连接。(笛卡尔积)

该查询似乎为每个财政年度返回一些值。

鉴于此表:

create table a (id int, foo int);
create table c (id int);
insert into a values (1,1),(2,2),(3,3);
insert into c values (10),(20);

select * from a, c;

select * from a cross join c;
Run Code Online (Sandbox Code Playgroud)
身份证 | 富| ID
-: | --: | -:
 1 | 1 | 10
 2 | 2 | 10
 3 | 3 | 10
 1 | 1 | 20
 2 | 2 | 20
 3 | 3 | 20

db<>在这里摆弄

再举一个例子:

create table a (id int, foo int);
create table b (id int, foo int);
create table c (id int);
create table d (id int);
insert into a values (1,1),(2,2),(3,3);
insert into b values (1,1),(2,2),(3,3);
insert into c values (10),(20);
insert into d values (1),(2);
Run Code Online (Sandbox Code Playgroud)
select * from a join b on a.id = b.id       ,     c join d on d.id = a.id ;
Run Code Online (Sandbox Code Playgroud)

Msg 4104 Level 16 State 1 Line 1
无法绑定多部分标识符“a.id”。

但如果你交叉加入它:

select * from a join b on a.id = b.id  cross join  c join d on d.id = a.id ;
Run Code Online (Sandbox Code Playgroud)
身份证 | 富| 身份证 | 富| 身份证 | ID
-: | --: | -: | --: | -: | -:
 1 | 1 | 1 | 1 | 10 | 1
 1 | 1 | 1 | 1 | 20 | 1
 2 | 2 | 2 | 2 | 10 | 2
 2 | 2 | 2 | 2 | 20 | 2

db<>在这里摆弄


Max*_*rek 7

你知道这种连接方法吗?

SELECT *
FROM table1, table2
WHERE table1.pk = table2.fk
Run Code Online (Sandbox Code Playgroud)

如果将 WHERE 子句排除在该查询之外,则会得到笛卡尔积,这与 CROSS JOIN 相同:

SELECT *
FROM table1
CROSS JOIN table2
Run Code Online (Sandbox Code Playgroud)

您的查询看起来像是将连接方法与 INNER JOIN 语法相结合。这在逻辑上是一样的:

SELECT *     
FROM GLAccounts
INNER JOIN GLCharts
    ON glaGLChartID = glcGLChartID
LEFT JOIN GLCategories
    ON glcGLCategoryID = gltGLCategoryID
INNER JOIN GLDepartments
    ON glaGLDepartmentID = gldGLDepartmentID
INNER JOIN GLDivisions
    ON glaGLDivisionID = glvGLDivisionID
CROSS JOIN GLFiscalYearPeriods                
INNER JOIN GLFiscalYears
    ON glfGLFiscalYearID = glzGLFiscalYearID
Run Code Online (Sandbox Code Playgroud)

下面是一个例子:

DECLARE @t1 TABLE (t1id INT)
DECLARE @t2 TABLE (t2id INT, t1id INT)
DECLARE @t3 TABLE (t3id INT)

INSERT INTO @t1 VALUES (1), (2)
INSERT INTO @t2 VALUES (1, 1), (2, 1), (3, 2), (4, 2)
INSERT INTO @t3 VALUES (5), (6)

SELECT * 
FROM @t1 
INNER JOIN @t2 ON [@t2].t1id = [@t1].t1id
, @t3   
Run Code Online (Sandbox Code Playgroud)

返回:

t1id    t2id    t1id    t3id
1       1       1       5
1       1       1       6
1       2       1       5
1       2       1       6
2       3       2       5
2       3       2       6
2       4       2       5
2       4       2       6
Run Code Online (Sandbox Code Playgroud)

  • CROSS JOIN 和 CROSS APPLY 之间存在细微的差异和用例(我总是需要在需要时刷新我的记忆)。https://www.sqlservercentral.com/forums/topic/difference-between-cross-apply-and-cross-join#post-1100829 (3认同)

Han*_*dyD 5

连接的逗号语法是 ANSI SQL 标准(我认为是 SQL-89,但我可能是错的)中较旧的语法,后来更新(我认为 SQL-92,再次可能是错误的)以使用更明确的语法也更具可读性。它被称为“隐式连接表示法”,与“显式连接表示法”的实际 JOIN 子句形成对比。

逗号语法意味着隐式连接而不是显式连接,例如在没有 WHERE 子句的示例代码中,逗号语法意味着 CROSS JOIN 以生成 JOIN 两侧所有行的笛卡尔积。

在首选的 SQL 标准中,您将使用显式符号 CROSS JOIN 子句来生成 JOIN。

链接:

加入 (SQL)

如何在 ANSI SQL 89 语法中执行 JOIN?

  • 两种语法(逗号或隐式连接)和(JOIN ON 运算符)在当前 SQL 标准以及 92 和现在之间的所有版本中都是有效的。 (2认同)