Sql 从扩展行的两个表中选择数据

Sql 从扩展行的两个表中选择数据,sql,sql-server,backup,Sql,Sql Server,Backup,我的问题是: 我有两张桌子。一个携带真实数据,另一个用作备份。每当实际数据发生更改时,触发器就会将原始行复制到备份表中 我需要的是以下内容: 我想选择所有原始真实数据。这意味着真实数据表中从未更改的所有条目以及备份表中第一次插入的所有数据 想象一下这些表格: ╔════════╦══════════╗ ╔══════════╦════════╦══════════╗ ║ RealId ║ Numeric ║ ║ BackupId ║ RealId ║ Numeric ║ ╠════════╬

我的问题是:

我有两张桌子。一个携带真实数据,另一个用作备份。每当实际数据发生更改时,触发器就会将原始行复制到备份表中

我需要的是以下内容:

我想选择所有原始真实数据。这意味着真实数据表中从未更改的所有条目以及备份表中第一次插入的所有数据

想象一下这些表格:

╔════════╦══════════╗ ╔══════════╦════════╦══════════╗
║ RealId ║ Numeric  ║ ║ BackupId ║ RealId ║ Numeric  ║
╠════════╬══════════╣ ╠══════════╬════════╬══════════╣
║      1 ║        3 ║ ║        1 ║      1 ║        7 ║
║      2 ║       19 ║ ║        2 ║      1 ║        9 ║
║      3 ║       24 ║ ║        3 ║      1 ║       14 ║
║      4 ║        5 ║ ║        4 ║      2 ║        2 ║
║      5 ║       23 ║ ║        5 ║      3 ║       13 ║
╚════════╩══════════╝ ║        6 ║      5 ║        9 ║
                      ║        7 ║      5 ║        4 ║
                      ╚══════════╩════════╩══════════╝
我的目标是创建一个查询,该查询将返回如下内容:

╔══════════╦════════╦══════════╗
║ BackupId ║ RealId ║ Numeric  ║
╠══════════╬════════╬══════════╣
║ 1        ║      1 ║        7 ║
║ 4        ║      2 ║        2 ║
║ 5        ║      3 ║       13 ║
║ NULL     ║      4 ║        5 ║
║ 6        ║      5 ║        9 ║
╚══════════╩════════╩══════════╝
SELECT NULL AS BackupId, A.* FROM real-table A
WHERE NOT EXISTS (
    SELECT * 
    FROM backup-table B
    WHERE B.RealId = A.RealId
)

union all

Select C.* FROM backup-table C
INNER JOIN (
    SELECT MIN(BackupId) AS BackupId, 
           RealId
        FROM backup-table 
        GROUP BY RealId 
    ) D
on D.BackupId = C.BackupId

ORDER BY RealId Asc
如您所见,我始终希望返回备份表中使用特定Realid创建的第一个条目。(RealId和BackupId总是唯一的)

我想到的一个方法是

SELECT MIN(BackupId), RealId
FROM BackupTable
GROUP BY RealId
至于真正的桌子,我想到了

SELECT *
FROM real-table A
WHERE NOT EXISTS (
     SELECT * 
     FROM backup-table B
     WHERE B.RealId = A.RealId
)
但我实在想不出正确的方法来组合这些表。

使用窗口功能:

Create table #Real (RealID int, [Numeric] int)

Create table #Backup (BackupID int, RealID int, [Numeric] int)

Insert into #Real values(1, 3)
Insert into #Real values(2, 19)
Insert into #Real values(3, 24)
Insert into #Real values(4, 5)
Insert into #Real values(5, 23)

Insert into #Backup values (1, 1, 7)
Insert into #Backup values (2, 1, 9)
Insert into #Backup values (3, 1, 14)
Insert into #Backup values (4, 2, 2)
Insert into #Backup values (5, 3, 13)
Insert into #Backup values (6, 5, 9)
Insert into #Backup values (7, 5, 4)

Select distinct 
First_Value(b.[BackupID]) over (partition by r.RealID order by b.BackupID) as [BackupID]
    , r.RealID as [RealID]
    , isnull(First_Value(b.[Numeric]) over (partition by r.RealID order by b.BackupID), r.numeric) as [Numeric]
from #Real r 
left join #Backup b on r.realID = b.realid
order by r.[RealID]
使用窗口功能:

Create table #Real (RealID int, [Numeric] int)

Create table #Backup (BackupID int, RealID int, [Numeric] int)

Insert into #Real values(1, 3)
Insert into #Real values(2, 19)
Insert into #Real values(3, 24)
Insert into #Real values(4, 5)
Insert into #Real values(5, 23)

Insert into #Backup values (1, 1, 7)
Insert into #Backup values (2, 1, 9)
Insert into #Backup values (3, 1, 14)
Insert into #Backup values (4, 2, 2)
Insert into #Backup values (5, 3, 13)
Insert into #Backup values (6, 5, 9)
Insert into #Backup values (7, 5, 4)

Select distinct 
First_Value(b.[BackupID]) over (partition by r.RealID order by b.BackupID) as [BackupID]
    , r.RealID as [RealID]
    , isnull(First_Value(b.[Numeric]) over (partition by r.RealID order by b.BackupID), r.numeric) as [Numeric]
from #Real r 
left join #Backup b on r.realID = b.realid
order by r.[RealID]

对于2012年之前的任何人

(*现在编辑为假设所有realid都存在于real表中)


对于2012年之前的任何人

(*现在编辑为假设所有realid都存在于real表中)


我在网上找到了这篇文章:

这个问题的答案帮助我制定了这样一个解决方案:

╔══════════╦════════╦══════════╗
║ BackupId ║ RealId ║ Numeric  ║
╠══════════╬════════╬══════════╣
║ 1        ║      1 ║        7 ║
║ 4        ║      2 ║        2 ║
║ 5        ║      3 ║       13 ║
║ NULL     ║      4 ║        5 ║
║ 6        ║      5 ║        9 ║
╚══════════╩════════╩══════════╝
SELECT NULL AS BackupId, A.* FROM real-table A
WHERE NOT EXISTS (
    SELECT * 
    FROM backup-table B
    WHERE B.RealId = A.RealId
)

union all

Select C.* FROM backup-table C
INNER JOIN (
    SELECT MIN(BackupId) AS BackupId, 
           RealId
        FROM backup-table 
        GROUP BY RealId 
    ) D
on D.BackupId = C.BackupId

ORDER BY RealId Asc

然而,我想用cloudsafes的答案来测试这一点,看看哪一个性能更好。

我发现这篇文章是这样的:

这个问题的答案帮助我制定了这样一个解决方案:

╔══════════╦════════╦══════════╗
║ BackupId ║ RealId ║ Numeric  ║
╠══════════╬════════╬══════════╣
║ 1        ║      1 ║        7 ║
║ 4        ║      2 ║        2 ║
║ 5        ║      3 ║       13 ║
║ NULL     ║      4 ║        5 ║
║ 6        ║      5 ║        9 ║
╚══════════╩════════╩══════════╝
SELECT NULL AS BackupId, A.* FROM real-table A
WHERE NOT EXISTS (
    SELECT * 
    FROM backup-table B
    WHERE B.RealId = A.RealId
)

union all

Select C.* FROM backup-table C
INNER JOIN (
    SELECT MIN(BackupId) AS BackupId, 
           RealId
        FROM backup-table 
        GROUP BY RealId 
    ) D
on D.BackupId = C.BackupId

ORDER BY RealId Asc

但是,我想用CloudSafe的答案来测试这一点,看看哪一个性能更好。

我想你已经差不多做到了,但是不要在一个EXISTS中使用你的派生表,而是从实表内部连接到它。你有一个实例,即实表中存在一个项,而不是备份。一个项可以存在于备份中,但不存在于实际中,这是否也是有效的?@SimonB real table可以包含具有RealId的行,而不包含备份表,以包含具有相同RealId的行。但是备份表总是有一个RealId行,RealId行也存在于实际表中。我认为您基本上就在那里,但是不要在一个exists中使用您的派生表,从实际表内部连接到它。您的情况是,实际表中存在一个项,而不是备份。一个项可以存在于备份中,但不存在于实际中,这是否也是有效的?@SimonB real table可以包含具有RealId的行,而不包含备份表,以包含具有相同RealId的行。但是备份表总是有一个RealId行,RealId也存在于real table中,如果两个表都有20多个列,这将如何扩展?[Numeric]只是一个示例,表明数据与每列的SELECT不同:,isnull(第一个值(b[Col1])over(按r.RealID顺序按b.BackupID划分),r.Col1)as[Col1]对于给定的示例,您的答案是正确的,并且比我编的答案更有效。因此,您的答案应该是可接受的答案。如果两个表都有20多列,这将如何扩展?[Numeric]只是一个示例,表明数据与每列的SELECT不同:,isnull(第一个值(b[Col1])over(按r.RealID顺序按b.BackupID划分),r.Col1)as[Col1]对于给定的示例,您的答案是正确的,并且比我编的答案更有效。因此,您的答案应该是可接受的答案。执行计划在这里:36%对64%对于多个数字列,您提供的解决方案会更好。执行计划在这里:36%对64%对于多个数字列,您提供的解决方案会更好。