简体   繁体   中英

How to create a view which merges two tables?

I have two tables which have the exact same structure. Both tables can store the same data with different primary keys (autoincremented integers). Therefore, there is a third table which lists which two primary keys list the same data. However, there also exist rows which don't exist in the other. Therefore, a simple join won't work since you will have two rows with the same primary key but different data. Therefore, is there a way of reassigning primary keys to unused values in the view?

Table1

ID    name
 1     Adam
 2     Mark
 3     David
 4     Jeremy

Table2

ID    name
 1     Jessica
 2     Jeremy
 3     David
 4     Mark

Table3

T1ID  T2ID
 2     4
 3     3
 4     2

I am looking for a result table like the following:

Result

ID    name
 1     Adam
 2     Mark
 3     David
 4     Jeremy
 5     Jessica

The real heart of the question is how i can assign the temporary fake id of 5 to Jessica and not just some random number. The rule I want for the ids is that if the row exists in the first table, then use its own id. Otherwise, use the next id that an insert statement would have generated (the column is on autoincrement).

Answer to edited question

select id, name from table1
union all
select X.offset + row_number() over (order by id), name
from (select MAX(id) offset from table1) X
cross join table2
where not exists (select * from table3 where t2id = table2.id)

The MAX(id) is used to "predict" the next identity that would occur if you merged the data from the 2nd table into the first. If Table3.T2ID exists at all, it means that it is already included in table1.

Using the test data below

create table table1 (id int identity, name varchar(10))
insert table1 select 'Adam' union all
select 'Mark' union all
select 'David' union all
select 'Jeremy'

create table table2 (id int identity, name varchar(10))
insert table2 select 'Jessica' union all
select 'Jeremy' union all
select 'David' union all
select 'Mark'

create table table3 (t1id int, t2id int)
insert table3 select 2,4 union all
select 3,3 union all
select 4,2


Answer to original question below

So the 3rd table is the one you want to build (a view instead of a table)?

select newid=row_number() over (order by pk_id), *
from
(
    select a.*
    from tblfirst a
    UNION ALL
    select b.*
    from tblsecond b
) X

The data will contain a unique newid value for each record, whether from first or second table. Change pk_id to your primary key column name.

If I understand you correct, following might work

  1. Select everything from your first table
  2. Select everything from your second table that is not linked to your third table
  3. Combine the results

Test data

DECLARE @Table1 TABLE (ID INTEGER IDENTITY(1, 1), Value VARCHAR(32))
DECLARE @Table2 TABLE (ID INTEGER IDENTITY(1, 1), Value VARCHAR(32))
DECLARE @Table3 TABLE (T1ID INTEGER, T2ID INTEGER)


INSERT INTO @Table1 VALUES ('Adam')
INSERT INTO @Table1 VALUES ('Mark')
INSERT INTO @Table1 VALUES ('David')
INSERT INTO @Table1 VALUES ('Jeremy')

INSERT INTO @Table2 VALUES ('Jessica')
INSERT INTO @Table2 VALUES ('Jeremy')
INSERT INTO @Table2 VALUES ('David')
INSERT INTO @Table2 VALUES ('Mark')

INSERT INTO @Table3 VALUES (2, 4)
INSERT INTO @Table3 VALUES (3, 3)
INSERT INTO @Table3 VALUES (4, 2)

SQL Statement

SELECT  ROW_NUMBER() OVER (ORDER BY ID), t1.Value
FROM    @Table1 t1
UNION ALL 
SELECT  ROW_NUMBER() OVER (ORDER BY ID) + offset, t2.Value
FROM    @Table2 t2
        LEFT OUTER JOIN @Table3 t3 ON t3.T2ID = t2.ID
        CROSS APPLY (
          SELECT  Offset = COUNT(*)
          FROM    @Table1
        ) offset
WHERE   t3.T2ID IS NULL   

Assuming you have below data, as I understand reading your question:

Table: T1
ID  name
--------
1   a
2   b
3   c

Table: T2
ID  name
--------
2   b
3   c
4   d

Table: Rel
ID1  ID2
--------
2   2
3   3

T1 has some data which is not in T2 and vice versa. Following query will give all data unioned

SELECT ROW_NUMBER() OVER (order by name) ID, Col
from 
(
SELECT ISNULL(T1.name,'') name
FROM T1 t1 LEFT JOIN Rel TR ON TR.ID1 = T1.ID
union
SELECT ISNULL(T2.name,'') name
FROM T2 t2 LEFT JOIN Rel TR ON TR.ID2 = T2.ID
) T

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM