加入非唯一列

时间:2015-11-02 23:11:59

标签: sql sql-server join

表1

1 A 1 1
2 A 1 2
5 A 1 1
6 B 2 1

表2

1 1 12
2 2 45
3 5 22
4 6 21

table1.col1是fK到table2.col2

您希望复制col2 = A的值,并且col2 = AA:

1 A  1 1
2 A  1 2
5 A  1 1
6 B  2 1
7 AA 1 1   <- New
8 AA 1 2   <- New
9 AA 1 1   <- New

如何将表2加入到新的结果集中,以便AA存在的值也存在?

想要的结果:

1 A  1 1 | 1 1 12
2 A  1 2 | 2 2 45
5 A  1 1 | 3 5 22
6 B  2 1 | 4 6 21
7 AA 1 1 | 1 1 12
8 AA 1 2 | 2 2 45
9 AA 1 1 | 3 5 22

3 个答案:

答案 0 :(得分:1)

未测试:

逻辑似乎很稳固,但我没有数据,测试环境可以尝试这个... 您可以使用union和(内联视图或公用表表达式)来实现此目的。

首先,我们使用两组所需数据构建table1(下面的内联视图A)。这种方法使连接变得简单。这是使用union语句和硬编码AA值完成的,同时将集合限制为只有A,然后在基集中联合。

然后我们正常加入table2。

我使用了row_number()并按照col 2的顺序来识别各个值以增加最大ID。 1为第一行,第二行为a,第三行为3,第三行为a,基于种子为6,这是table1中的最大值。

我使用parent_ID来始终识别要加入table2的相关记录。

内联视图

Select *  --(though you should spell out desired columns)
from (Select ROW_NUMBER() OVER(ORDER BY Col2)+C.mID, 'AA', col3, col4, col1 as Parent_ID
      from table1
      CROSS JOIN (select max(col1) mID from table1) C  
      where table1.col2 = 'A'
  record 
      UNION ALL
      Select col1, Col2, col3, col4, col1 as Parent_ID
      from table1)  A

INNER JOIN table2
 on table2.col2 = A.parent_ID

CTE:

With cte as (Select  ROW_NUMBER() OVER(ORDER BY Col2)+C.mID col1, 'AA' col2, col3, col4, col1 as Parent_Id
    FROM table1
    CROSS JOIN (select max(col1) mID from table1) C
    WHERE table1.col2 = 'A'
    UNION ALL
    SELECT col1, Col2, col3, col4, col1 as Parent_Id
    from table1) 

 SELECT * --(though you should spell out desired columns)
 FROM cte
 INNER JOIN table2
   on table2.col2 = cte.Parent_Id

答案 1 :(得分:0)

单独考虑每个值A / B / AA并使用窗口函数来查找col3和col4上的滞后导线

对待每个&#34; prev_col3,col3,next_col3,prev_col4,col4,next_col4&#34;作为一个独特的&#34;背景&#34;标识符并加入其中。这就是我们如何避免将第7行与数据中的第9行混淆;它们具有col3和col4的不同上一个/下一个滞后/超前值。

我们需要控制null情况(我将null设为-1)以使连接起作用。

您可以将其复制/粘贴到SQL Server中以使其正常工作:

CREATE TABLE #TABLE1 (col1 INT, col2 varchar(5), col3 INT, col4 INT)
CREATE TABLE #TABLE2 (col1 INT, col2 INT, col3 INT)

INSERT INTO #TABLE1
select 1 col1,'A' col2, 1 col3, 1 col4 union
select 2 col1,'A' col2, 1 col3, 2 col4 union
select 5 col1,'A' col2, 1 col3, 1 col4 union
select 6 col1,'B' col2, 2 col3, 1 col4 union
select 7 col1,'AA' col2, 1 col3, 1 col4 union
select 8 col1,'AA' col2, 1 col3, 2 col4 union
select 9 col1,'AA' col2, 1 col3, 1 col4 

INSERT INTO #TABLE2
select 1 col1, 1 col2, 12 col3 union
select 2 col1,2 col2, 45 col3 union
select 3 col1,5 col2, 22 col3 union
select 4 col1,6 col2, 21 col3


select 
    Bu.col1, bu.col2, bu.col3, bu.col4, t2.col1, t2.col2, t2.col3
from 
   (
    select 
       col1, col2,
       lag(col3) over (order by col1 asc) prev_col3,
       col3,
       lead(col3) over (order by col1 asc) next_col3,
       lag(col4) over (order by col1 asc) prev_col4,
       col4,
       lead(col4) over (order by col1 asc) next_col4
    from 
       #TABLE1 t1 where col2 in ('A')
    ) A   
    join 
   ( /*bu big union*/
    select 
       col1, col2,
       lag(col3) over (order by col1 asc) prev_col3,
       col3,
       lead(col3) over (order by col1 asc) next_col3,
       lag(col4) over (order by col1 asc) prev_col4,
       col4,
       lead(col4) over (order by col1 asc) next_col4
    from 
       #TABLE1 t1 where col2 in ('A')
    UNION
    select 
       col1, col2,
       lag(col3) over (order by col1 asc) prev_col3,
       col3,
       lead(col3) over (order by col1 asc) next_col3,
       lag(col4) over (order by col1 asc) prev_col4,
       col4,
       lead(col4) over (order by col1 asc) next_col4
    from 
       #TABLE1 t1 where col2 in ('AA')
    ) bu
    on 
   ( 
    a.col3 = bu.col3 and isnull(a.prev_col3,-1) = isnull(bu.prev_col3,-1) and 
    isnull(a.next_col3,-1) = isnull(bu.next_col3,-1) and 
    a.col4 = bu.col4 and isnull(a.prev_col4,-1) = isnull(bu.prev_col4,-1) and 
    isnull(a.next_col4,-1) = isnull(bu.next_col4 ,-1)
    )
    join
    #TABLE2 t2
    on 
    a.col1 = t2.col2
    UNION
    select 
       t1.col1, t1.col2, t1.col3, t1.col4,
       t2.col1, t2.col2, t2.col3
    from 
       #TABLE1 t1 
       join #TABLE2 t2 on t1.col1 = t2.col2
    where t1.col2 = 'B'
    order by 1 asc

drop table #TABLE1
drop table #TABLE2

答案 2 :(得分:0)

    declare @maxCol1 int

    select @maxCol1 = max(col1)
    from table1


    select a.col1,
    a.col2,
    a.col3,
    a.col4,
    b.col1,
    b.col2,
    b.col3
    from table1 a
    join table2 b
    on a.col1 = b.col2

    union all

    select a.col1 + @maxCol1 as col1,
    a.col2 + a.col2 as col2,
    a.col3,
    a.col4,
    b.col1,
    b.col2,
    b.col3
    from table1 a
    join table2 b
    on a.col1 = b.col2
    where a.col2 = 'A'