【问题标题】:All records from first table and extra records from second table第一个表中的所有记录和第二个表中的额外记录
【发布时间】:2022-01-27 14:46:33
【问题描述】:

我有 2 个表,我想从第一个表中获取所有记录,并从第二个表中获取额外记录。

表 A

+-----+---------+---------+
| ID  | NAME    | TASK    |
+-----+---------+---------+
| 101 | Alan    | Prepare |
+-----+---------+---------+
| 102 | Fabien  | Approve |
+-----+---------+---------+
| 103 | Christy | Plan    |
+-----+---------+---------+
| 104 | David   | Approve |
+-----+---------+---------+
| 105 | Eric    | Set     |
+-----+---------+---------+

表 B

+-----+---------+---------+
| ID  | NAME    | TASK    |
+-----+---------+---------+
| 101 | Richy   | Prepare |
+-----+---------+---------+
| 103 | Girish  | Plan    |
+-----+---------+---------+
| 106 | Fleming | Approve |
+-----+---------+---------+
| 107 | Ian     | Set     |
+-----+---------+---------+

预期输出

+-----+---------+---------+
| ID  | NAME    | TASK    |
+-----+---------+---------+
| 101 | Alan    | Prepare |
+-----+---------+---------+
| 102 | Fabien  | Approve |
+-----+---------+---------+
| 103 | Christy | Plan    |
+-----+---------+---------+
| 104 | David   | Approve |
+-----+---------+---------+
| 105 | Eric    | Set     |
+-----+---------+---------+
| 106 | Fleming | Approve |
+-----+---------+---------+
| 107 | Ian     | Set     |
+-----+---------+---------+ 

我尝试过使用LEFT JOIN。但我只从左表得到所有。

select * from A left join B on A.ID=B.ID and B.ID is NULL

我也尝试过UNIONUNION ALL,但由于Name 在两个表中可能不同,我得到了两条记录。一种解决方案可能是使用NOT IN,但这对我来说很重要,因为我在这里将大查询称为表 A 和 B。我不知道我错过了什么。它应该很简单,但现在我并不感到惊讶。请帮忙。

【问题讨论】:

  • Fleming 和 Ian 在 [A] 中不存在,因此它们根本不可能出现在结果集中,因为它基于 [A]。这个连接条件A.ID=B.ID and B.ID is NULL 是逻辑废话。加入一列,然后在同一列中过滤 NULL 将不匹配 [B] 中的任何内容 - 从有效和逻辑上讲,您根本没有真正加入。您应该明确定义您的表格代表什么以及您的目标是什么。

标签: sql sql-server join sql-server-2019


【解决方案1】:

我正在考虑在 ROW_NUMBER 和计算列的帮助下建立联合:

WITH cte AS (
    SELECT ID, NAME, TASK, 1 AS SRC FROM TableA
    UNION ALL
    SELECT ID, NAME, TASK, 2 FROM TableB
),
cte2 AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY SRC) rn
    FROM cte
)

SELECT ID, NAME, TASK
FROM cte2
WHERE rn = 1;

这里的想法是构建一个包含两个表中所有记录的中间表。我们引入了一个计算列来跟踪表源,并赋予 A 记录比 B 记录更高的优先级。使用ROW_NUMBER 允许我们选择A 记录而不是具有相同ID 的B 记录。

【讨论】:

    【解决方案2】:

    Full outer join 将起作用,因为完全连接将从两个表中获取所有匹配和不匹配的记录

    ;with tablea as 
    (
    select  101 as id,  'Alan'    name, 'Prepare ' as task
    union select  102 , 'Fabien'  , 'Approve' 
    union select  103 , 'Christy' , 'Plan    '
    union select  104 , 'David'   , 'Approve '
    union select  105 , 'Eric'    , 'Set   ')
    ,tableb as (
    select  101 as ID  ,'Richy  ' as NAME   ,' Prepare ' as TASK     
    union select  103 ,'Girish ',' Plan    '
    union select  106 ,'Fleming',' Approve '
    union select  107 ,'Ian    ',' Set '
    )
    
    select isnull(a.id,b.id) as id, isnull(a.name,b.name) as name, isnull(a.task,b.TASK) from tablea a
    full outer join tableb b on a.id = b.ID
    

    结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-26
      相关资源
      最近更新 更多