SQL 连接的补充?需要 T-SQL 帮助

Posted

技术标签:

【中文标题】SQL 连接的补充?需要 T-SQL 帮助【英文标题】:Complement of a SQL Join? T-SQL help needed 【发布时间】:2012-03-21 05:40:07 【问题描述】:

我会尽量让我的问题听起来不那么令人困惑。对于任何措辞错误,我提前道歉,因为我会尽可能地表达我的问题:

使用 T-SQL 我需要编写一个连接语句来获取在表 A 和表 B 中匹配的所有结果

与 (!)

另一个连接语句(或第一个连接的延续)返回表 A 中在表 B 中没有匹配项的所有结果,但在第二个结果集中,我需要将其中一个列设置为“ N/A" 以识别不匹配的记录。

换句话说,我需要能够返回表 A 中的所有内容但也能识别 B 中不匹配的行的东西。然后在报告中使用该信息。

这是我目前所拥有的:

我已经完成了第一部分:

LEFT OUTER JOIN dbo.chart B
ON B.UserName = A.user_name

这让我得到匹配的记录和匹配的记录

我尝试添加第二个连接:

JOIN dbo.chart
ON NOT EXISTS (select * from B.UserName = A.user_name)

希望它能让我得到不匹配的记录(我打算然后在感兴趣的列上使用 REPLACE 来标记该列“N/A”)但是我的合成器有一些明显的问题,因为它会产生异常。

我的问题是我需要进行哪些更改才能获得您需要的结果。我确实知道我需要至少有一个连接,因为我还有查询的其他部分可以使用。我只是不知道我是否需要一个连接返回两组数据,实际上我确实需要第二个连接来处理不匹配的记录。

希望这不会太混乱。任何帮助将不胜感激。

谢谢!

更新:我想强调一下,我考虑使用第二个连接而不是一次获取所有结果的原因是因为我需要正确识别和标记那些在所有内容中都不匹配的行我回来了。

【问题讨论】:

left outer join 应该给你你想要的。来自 A 并连接到 B 的所有行,其中存在匹配项。您在表 B 中的某些列上有 WHERE 条件吗?如果这样做,那会使外连接变为内连接,您需要将对表 B 中的列的检查移至连接子句。 感谢您的回复,米凯尔。我想要完成的最重要的事情(也是我考虑使用第二个连接的主要原因)是能够识别和标记哪些行匹配,哪些不匹配。 您不需要额外的加入。使用 coalesce,正如 Mark 在对 Dems 答案的评论中所建议的那样。 我会这样做的。谢谢。 实际上,我不完全确定coalesce 应该去哪里。 Mark 指的是哪个 select 子句? 【参考方案1】:

我不确定第二次加入你要去哪里。 LEFT JOIN 似乎可以做你想做的一切......

DECLARE @tableA TABLE (a_id INT) INSERT INTO @tableA VALUES (1), (2), (3), (4)
DECLARE @tableB TABLE (b_id INT) INSERT INTO @tableB VALUES      (2), (3)

SELECT * FROM @tableA AS A LEFT JOIN @tableB AS B on A.a_id = b.b_id

 a_id | b_id
------+------
   1  | NULL
   2  |  2
   3  |  3
   4  | NULL

除非您的意思是实际上将 3 个表连接在一起?

DECLARE @org    TABLE (o_io INT) INSERT INTO @org    VALUE       (2), (3), (4)
DECLARE @tableA TABLE (a_id INT) INSERT INTO @tableA VALUES (1), (2), (3), (4)
DECLARE @tableB TABLE (b_id INT) INSERT INTO @tableB VALUES      (2), (3)

SELECT
  *
FROM
  @org        AS O
INNER JOIN
  @tableA     AS A
    ON O.o_id = A.a_id
LEFT JOIN
  @tableB     AS B
    ON A.a_id = b.b_id

 o_id | a_id | b_id
------+------+------
   2  |   2  |  2
   3  |   3  |  3
   4  |   4  | NULL

【讨论】:

+1 在 select 子句中添加 coalesce(B.UserName,'N/A')(或其他适当的 tableB 列)以满足 OP 对没有匹配 tableB 记录的“N/A”标签记录的要求。 Dems,感谢您的回复。这实际上是我正在使用的两个表(dbo.chart 和 dbo.orgchart 是一个并且相同)。我会更正我在问题中的类型。 马克,我会结合 Dems 写的内容尝试您的建议。谢谢!【参考方案2】:

样本数据:

declare @TableA table
(
  TableAID int,
  TableAName varchar(10)
)

declare @TableB table
(
  TableBID int,
  TableBName varchar(10),
  TableAID int
)

insert into @TableA values
(1, 'A 1'),
(2, 'A 2'),
(3, 'A 3')

insert into @TableB values
(1, 'B 1', 1),
(2, 'B 2', 2)

不适用,而不是 TableBName:

select A.TableAName,
       coalesce(B.TableBName, 'N/A') as TableBName
from @TableA as A
  left outer join @TableB as B
    on A.TableAID = B.TableAID

结果:

TableAName TableBName
---------- ----------
A 1        B 1
A 2        B 2
A 3        N/A

不适用的额外列:

select A.TableAName,
       B.TableBName,
       case when B.TableBID is null 
         then 'N/A' 
         else '' 
       end as TableBPresent
from @TableA as A
  left outer join @TableB as B
    on A.TableAID = B.TableAID    

结果:

TableAName TableBName TableBPresent
---------- ---------- -------------
A 1        B 1        
A 2        B 2        
A 3        NULL       N/A

【讨论】:

这很有帮助。谢谢! 这里有一个更正使它完美:select A.TableAName, coalesce(B.TableBName, 'N/A') as TableBName from @TableA as A left outer join select TableID from B on A.TableAID = B.TableAID @user1179071 您的查询无效 它对我有用。所有东西的组合方式可能会有所不同。【参考方案3】:

尝试使用联合:

select A.id, b.id, b.desc from tablea A LEFT OUTER JOIN dbo.chart B
ON B.UserName = A.user_name

UNION 

select a.id, 0, 'N/A' from tablea where NOT EXISTS (select * from B.UserName = A.user_name)

【讨论】:

你需要修复你的 NOT EXISTS。 Select * from B where ... 而且应该是内连接。 谢谢。尝试所有建议。

以上是关于SQL 连接的补充?需要 T-SQL 帮助的主要内容,如果未能解决你的问题,请参考以下文章

SQL多表连接查询补充

Mysql最后补充+Java连接数据库

数据库 Mysql内容补充二

在 T-SQL 中使用 PIVOT 需要帮助

需要帮助将 T-SQL 转换为 PostgreSQL

需要帮助优化 T-SQL 查询