Select 来自 2 个表的数据,它们扩展了行
Select Data from 2 tables where they extend the rows
我的问题是这样的:
我有两个 table。一个承载真实数据,另一个用作备份。每当真实数据发生变化时,触发器都会将原始行复制到备份中-table.
我需要的是:
我要select所有原始真实数据。这意味着从未更改过的真实数据 table 中的所有条目以及首次插入的备份 table 中的所有数据。
想象一下这些 table:
╔════════╦══════════╗ ╔══════════╦════════╦══════════╗
║ 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 ║
╚══════════╩════════╩══════════╝
我的目标是进行查询 return 如下所示:
╔══════════╦════════╦══════════╗
║ BackupId ║ RealId ║ Numeric ║
╠══════════╬════════╬══════════╣
║ 1 ║ 1 ║ 7 ║
║ 4 ║ 2 ║ 2 ║
║ 5 ║ 3 ║ 13 ║
║ NULL ║ 4 ║ 5 ║
║ 6 ║ 5 ║ 9 ║
╚══════════╩════════╩══════════╝
如您所见,我一直想 return 使用备份中的特定 Realid 创建的第一个条目 - table。 (RealId 和 BackupId 始终是唯一的)
我想到的一种方法是
SELECT MIN(BackupId), RealId
FROM BackupTable
GROUP BY RealId
至于真正的-table,我想到了
SELECT *
FROM real-table A
WHERE NOT EXISTS (
SELECT *
FROM backup-table B
WHERE B.RealId = A.RealId
)
但我实在想不出正确的方法来组合 tables。
使用window函数:
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 都将存在于真实 table)
SELECT
firstB.minBU AS [first Backup]
, R.realid
, ISNULL(B.numeric, R.numeric) AS [original value]
FROM
(SELECT realid, MIN(backupid) AS minBU
FROM test.[backup] AS backup_1 GROUP BY realid
) AS firstB
INNER JOIN
test.[backup] AS B
ON firstB.realid = B.realid AND firstB.minBU = B.backupid
RIGHT OUTER JOIN
test.real AS R ON firstB.realid = R.realid
我在 SO:
上找到了这个 post
Select from table if record found in another table
这个问题的答案帮助我制定了这样的解决方案:
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 答案进行测试,看看哪个性能更好。
我的问题是这样的:
我有两个 table。一个承载真实数据,另一个用作备份。每当真实数据发生变化时,触发器都会将原始行复制到备份中-table.
我需要的是:
我要select所有原始真实数据。这意味着从未更改过的真实数据 table 中的所有条目以及首次插入的备份 table 中的所有数据。
想象一下这些 table:
╔════════╦══════════╗ ╔══════════╦════════╦══════════╗
║ 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 ║
╚══════════╩════════╩══════════╝
我的目标是进行查询 return 如下所示:
╔══════════╦════════╦══════════╗
║ BackupId ║ RealId ║ Numeric ║
╠══════════╬════════╬══════════╣
║ 1 ║ 1 ║ 7 ║
║ 4 ║ 2 ║ 2 ║
║ 5 ║ 3 ║ 13 ║
║ NULL ║ 4 ║ 5 ║
║ 6 ║ 5 ║ 9 ║
╚══════════╩════════╩══════════╝
如您所见,我一直想 return 使用备份中的特定 Realid 创建的第一个条目 - table。 (RealId 和 BackupId 始终是唯一的)
我想到的一种方法是
SELECT MIN(BackupId), RealId
FROM BackupTable
GROUP BY RealId
至于真正的-table,我想到了
SELECT *
FROM real-table A
WHERE NOT EXISTS (
SELECT *
FROM backup-table B
WHERE B.RealId = A.RealId
)
但我实在想不出正确的方法来组合 tables。
使用window函数:
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 都将存在于真实 table)
SELECT
firstB.minBU AS [first Backup]
, R.realid
, ISNULL(B.numeric, R.numeric) AS [original value]
FROM
(SELECT realid, MIN(backupid) AS minBU
FROM test.[backup] AS backup_1 GROUP BY realid
) AS firstB
INNER JOIN
test.[backup] AS B
ON firstB.realid = B.realid AND firstB.minBU = B.backupid
RIGHT OUTER JOIN
test.real AS R ON firstB.realid = R.realid
我在 SO:
上找到了这个 postSelect from table if record found in another table
这个问题的答案帮助我制定了这样的解决方案:
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 答案进行测试,看看哪个性能更好。