Full Outer Join self为null值

时间:2017-11-17 17:45:19

标签: sql-server tsql outer-join self-join

我想做一个包含空值的完整外部自联接。例如,如果表Data看起来像:

N   Name   Val
--------------
1   ABC    8
1   DEF    7
2   ABC    9
2   XYZ    6

(其中N是一个通用索引列,用于在顺序组上启用自联接)并且我这样做:

SELECT COALESCE(a.n, b.n) as n, COALESCE(a.Name, b.Name) as Name, a.Val as A, b.Val as B
FROM Data a 
     FULL OUTER JOIN Data b on a.N = b.N - 1 and a.Name = b.Name

我想:

N  Name  A    B
---------------
1  ABC   8    9
1  DEF   7    NULL
1  XYZ   NULL 6

但我得到的更像是交叉加入:

n  Name  A    B
--------------
1  ABC   8    9
1  DEF   7    NULL
2  ABC   9    NULL
2  XYZ   6    NULL
1  ABC   NULL    8
1  DEF   NULL    7
2  XYZ   NULL    6

如何执行此完全外连接以获得精简的自连接结果?

注意:在实践中,列N是一个通用索引,因此需要命名N值的解决方案并不实用。)

4 个答案:

答案 0 :(得分:1)

到目前为止,我只能看到这样做是一个联盟。以及左右连接,因为您改变后的标准。

SELECT COALESCE(a.Name, b.Name) as Name, a.Val as A, b.Val as B
FROM Data a 
LEFT JOIN Data b on a.Name = b.Name   
   and B.N = 2
WHERE A.N = 1 
UNION 
SELECT COALESCE(a.Name, b.Name) as Name, a.Val as A, b.Val as B
FROM Data a 
RIGHT JOIN Data b on a.Name = b.Name   
   and A.N = 1
WHERE B.N = 2

给我们:

+------+---+----+
| NAME | A |  B |
+------+---+----+
| ABC  | 8 |  9 |
| DEF  | 7 |    |
| XYZ  |   |  6 |
+------+---+----+

然而,这依赖于一个硬编码的N值,我认为这不是很有用......更好地工作。

答案 1 :(得分:1)

由于我们想要处理一个通用的自连接索引列N,让我们进一步扩展样本集:

create table #Data (n int, name char(3), val int)
insert into #Data values (1, 'ABC',8)
insert into #Data values (1, 'DEF',7)
insert into #Data values (2, 'ABC',9)
insert into #Data values (2, 'XYZ',6)
insert into #Data values (3, 'ABC',9)
insert into #Data values (3, 'DEF',5)
insert into #Data values (3, 'XYZ',4)

对于此示例,我们希望SQL生成此输出:

N  Name  A    B
---------------
1  ABC   8    9
1  DEF   7    NULL
1  XYZ   NULL 6
2  ABC   9    9
2  DEF   NULL 5
2  XYZ   6    4

以下代码适用于一般情况:

SELECT COALESCE(a.n, b.n-1) as i, COALESCE(a.Name, b.Name) as Name, a.Val as A, b.Val as B
FROM #Data a 
    FULL OUTER JOIN #Data b ON a.N = b.N - 1 AND a.Name = b.Name
WHERE a.n < (SELECT MAX(n) FROM #Data) -- Deals with end index case
    OR (a.n is null AND b.n-1 IN (SELECT DISTINCT n FROM #Data))
ORDER BY COALESCE(a.n, b.n-1), Name

要了解其工作原理,请注意,当a.N = 1我们想要n = 1所在的行时,一个很好的中间步骤是:

SELECT COALESCE(a.n, b.n - 1) as n, COALESCE(a.Name, b.Name) as Name,
    a.Val as A, b.Val as B 
FROM #Data a
    FULL OUTER JOIN #Data b ON a.N = b.N - 1 AND a.Name = b.Name

答案 2 :(得分:0)

请参阅以下代码:

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<style>
.phone{
    position: fixed; 
    top: 100px; 
    left: 0px; 
}
</style>

<div class="container-fluid">
    <div class="row" id="spec" >
       <div class="col-sm-12 col-md-6 text-center">        
            <div class="phone">
                <img src="https://www.bell.ca/Styles/wireless/all_languages/all_regions/catalog_images/iPhone_7/iPhone7_MatBlk_lrg1_en.png"/>
            </div>
       </div>

       <div class="col-sm-12 col-md-6 " >
          <section id="spec-text1" class="spec-text" style="height:400px">scrolling text in section1</section>
          <section id="spec-text1" class="spec-text" style="height:400px">scrolling text in section2</section>
          <section id="spec-text1" class="spec-text" style="height:400px">scrolling text in section3</section>
          <section id="spec-text1" class="spec-text" style="height:400px">scrolling text in section3</section>
          <section id="spec-text1" class="spec-text" style="height:400px">scrolling text in section3</section>
          <section id="spec-text1" class="spec-text" style="height:400px">scrolling text in section3</section>
          <section id="spec-text1" class="spec-text" style="height:400px">scrolling text in section3</section>
       </div>                  
    </div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

输出是这样的:

enter image description here

双方都有空白。

答案 3 :(得分:0)

也许这个:

SELECT [Name]
       ,[1]
       ,[2]
FROM [table]
PIVOT
(
    MAX([val]) FOR [N] IN ([1], [2])
) PVT;