SQL 服务器 - 内部和外部连接在一起
SQL Server - Inner and Outer join together
在为 SQL 服务器编写 SQL 查询时需要一些帮助。我有以下包含三个表的数据模型
Table 1
Seq ID Name
1 1234 Abc
2 4567 Pqr
3 7890 Xyz
Table 2
Seq Table1Id Table3Seq
1 1234 1
2 1234 2
3 7890 3
Table 3
Seq Status
1 Rejected
2 Accepted
3 Pending
我的要求如下。我想要 Table 1 中的所有记录以及 Table 3 中的最新状态(如果存在)。因此,正如我们在 Id 1234
中看到的那样,有两条记录在 Table 3 中匹配(通过 Table 2),但是我想要最新的已接受的记录。但是 Table 1 4567
中有一条记录,而 Table 2 中没有任何记录,所以我可以在 Status 上显示为空。
Number Name Status
1234 Abc Accepted
4567 Pqr
7890 Xyz Pending
我想,我们可能需要使用 Outer 和 Inner 连接在一起,但是到目前为止我无法找到正确的查询。当我尝试使用 MAX
仅使用外连接时,它仍然会针对 1234
提供两条记录,而当我使用内连接时,我不会在输出中获得记录 4567
。
select a.ID, a.Name, c.Status
from table1 a
left outer join (select max(b.seq) AS SEQ, b.table1id from table2 b group by b.table1id) t2 on a.id = t2.table1id
left outer join table2 t2b on t2.seq = t2b.seq and t2.table1id = t2b.table1id
left outer join table3 c on t2b.table3seq = c.seq
可能有更有效的方法来做到这一点,但这会给您带来您想要的结果。基本上将 table 1 连接到 table 2 的子集以获得每个记录的最大序列,然后再次连接到 table2 以获得 link 到 table 3、然后加入table3获取状态。
所有联接都保留在外部,因此您的 pqr 结果返回时状态为空。
使用两个连接:
SELECT Number, Name, Status FROM
(SELECT Table1.ID AS Number, Table1.Name, Table3.Status,
ROW_NUMBER() OVER (PARTITION BY Table1.Number ORDER BY table3.Seq DESC) AS RN
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID=Table2.Table1ID
LEFT OUTER JOIN Table3 ON Table3.seq=table2.Table3Seq)MyTable
WHERE MyTable.RN=1
在 SQL 服务器中执行此操作的一种方法是使用 outer apply
。这种方法往往性能最好:
select t1.*, t3.status
from table1 t1 outer apply
(select top 1 t3.*
from table2 t2 join
table3 t3
on t2.table3seq = t3.seq
where t1.id = t2.table1id
order by t2.id desc
) t3;
适当的索引是 table2(table1id, table3seq, id)
和 table3(seq, status)
。
在为 SQL 服务器编写 SQL 查询时需要一些帮助。我有以下包含三个表的数据模型
Table 1
Seq ID Name
1 1234 Abc
2 4567 Pqr
3 7890 Xyz
Table 2
Seq Table1Id Table3Seq
1 1234 1
2 1234 2
3 7890 3
Table 3
Seq Status
1 Rejected
2 Accepted
3 Pending
我的要求如下。我想要 Table 1 中的所有记录以及 Table 3 中的最新状态(如果存在)。因此,正如我们在 Id 1234
中看到的那样,有两条记录在 Table 3 中匹配(通过 Table 2),但是我想要最新的已接受的记录。但是 Table 1 4567
中有一条记录,而 Table 2 中没有任何记录,所以我可以在 Status 上显示为空。
Number Name Status
1234 Abc Accepted
4567 Pqr
7890 Xyz Pending
我想,我们可能需要使用 Outer 和 Inner 连接在一起,但是到目前为止我无法找到正确的查询。当我尝试使用 MAX
仅使用外连接时,它仍然会针对 1234
提供两条记录,而当我使用内连接时,我不会在输出中获得记录 4567
。
select a.ID, a.Name, c.Status
from table1 a
left outer join (select max(b.seq) AS SEQ, b.table1id from table2 b group by b.table1id) t2 on a.id = t2.table1id
left outer join table2 t2b on t2.seq = t2b.seq and t2.table1id = t2b.table1id
left outer join table3 c on t2b.table3seq = c.seq
可能有更有效的方法来做到这一点,但这会给您带来您想要的结果。基本上将 table 1 连接到 table 2 的子集以获得每个记录的最大序列,然后再次连接到 table2 以获得 link 到 table 3、然后加入table3获取状态。
所有联接都保留在外部,因此您的 pqr 结果返回时状态为空。
使用两个连接:
SELECT Number, Name, Status FROM
(SELECT Table1.ID AS Number, Table1.Name, Table3.Status,
ROW_NUMBER() OVER (PARTITION BY Table1.Number ORDER BY table3.Seq DESC) AS RN
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID=Table2.Table1ID
LEFT OUTER JOIN Table3 ON Table3.seq=table2.Table3Seq)MyTable
WHERE MyTable.RN=1
在 SQL 服务器中执行此操作的一种方法是使用 outer apply
。这种方法往往性能最好:
select t1.*, t3.status
from table1 t1 outer apply
(select top 1 t3.*
from table2 t2 join
table3 t3
on t2.table3seq = t3.seq
where t1.id = t2.table1id
order by t2.id desc
) t3;
适当的索引是 table2(table1id, table3seq, id)
和 table3(seq, status)
。