web-dev-qa-db-ja.com

T-SQLの奇妙なJOIN ON句

私はいくつかのレガシーコードを解きほぐしていて、これまでにこれまでに見たことがありません:

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

結合は機能しますが、ON句のT-SQL構文参照でコンマを使用していることはわかりません。

ここで何が起こっているのですか? TIA

18
Joseph Shirk

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;
 id | foo | id 
-:| -:| -:
 1 | 1 | 10 
 2 | 2 | 10 
 3 | 3 | 10 
 1 | 1 | 20 
 2 | 2 | 20 
 3 | 3 | 20 

db <> fiddle ここ

ちょうど別の例:

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);
select * from a join b on a.id = b.id       ,     c join d on d.id = a.id ;

メッセージ4104レベル16状態1行1
マルチパート識別子「a.id」をバインドできませんでした。

しかし、あなたがそれにクロスジョインした場合:

select * from a join b on a.id = b.id  cross join  c join d on d.id = a.id ;
 id | foo | id | foo | id | 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 <> fiddle ここ

20
McNets

この結合アプローチを知っていますか?

SELECT *
FROM table1, table2
WHERE table1.pk = table2.fk

そのクエリからWHERE句を除外すると、デカルト積が得られます。これは、CROSS JOINと同じです。

SELECT *
FROM table1
CROSS JOIN table2

クエリは、その結合アプローチと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

次に例を示します。

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   

戻り値:

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
7
Max Szczurek

結合のコンマ構文は、ANSI SQL標準の古い構文(SQL-89だと思いますが、私は間違っている可能性があります)ですが、より明示的な構文を使用するように後で更新されました(SQL-92はまた間違っていると思います)。また読みやすかったです。これは「暗黙的な結合表記」として知られていますが、「明示的な結合表記」である実際のJOIN句とは対照的です。

カンマ構文は、明示的な結合ではなく暗黙的な結合を意味します。たとえば、WHERE句のないサンプルコードでは、カンマ構文はCROSS JOINを意味し、JOINの両側のすべての行のデカルト積を生成します。

推奨されるSQL標準では、明示的な表記CROSS JOIN句を使用してJOINを生成します。

リンク:

結合(SQL)

ANSI SQL 89構文でJOINを実行するにはどうすればよいですか?

5
HandyD