我有以下情况。
我得到了一个表,里面有一些验证的、非验证的记录和(比方说)主验证的记录。编辑了一下。在表中,我得到了标准的唯一ID字段,但也有一列叫做VerifiedRecordID,指向表中的其他记录,或者它是NULL。
如果记录的VerifiedRecordID=NULL,则为非验证记录。
如果记录的VerifiedRecordID=some_id,那么这条记录是经过验证的,并且
ID=some_id的记录是主验证记录。
多条验证记录可能指向一条主验证记录,最后一条只是为验证记录提供验证数据,不能直接访问。最后一条只是为了给验证记录提供验证数据,不能直接访问。
但是还有一个因素决定记录是否被验证,不仅仅是这个字段,所以验证是由一个存储过程决定的。所以,如果你访问未验证的记录,它将返回其字段。如果访问经过验证的记录,它将忽略它的字段(ID除外),并返回它所指向的主验证记录的字段(ID除外)。
所以,我想创建一个存储过程,通过传递@ids参数从表中提取记录,其中可能包含已验证或未验证记录的id(但不包括主验证记录,因为它们不能直接访问)。这个我懂了。
DECLARE @verifiedMasterRecordsIds [dbo].[Ints]
INSERT INTO @verifiedMasterRecordsIds
EXEC sp_getVerifiedMasterRecordsIds
SELECT record.ID,
CASE
WHEN record.ID IN (SELECT ID FROM @verifiedMasterRecordsIds)
THEN verRecord.Field1
ELSE record.Field1
END AS Field1,
CASE
WHEN record.ID IN (SELECT ID FROM @verifiedMasterRecordsIds)
THEN verRecord.Field2
ELSE record.Field2
END as Field2,
CASE
WHEN record.ID IN (SELECT ID FROM @verifiedMasterRecordsIds)
THEN verRecord.Field3
ELSE record.Field3
END as Field3,
CASE
WHEN record.ID IN (SELECT ID FROM @verifiedMasterRecordsIds)
THEN verRecord.Field4
ELSE record.Field4
END AS Field4
INTO #TempRecords
FROM Records as record
LEFT JOIN Records as verRecord ON record.VerifiedRecordID=verRecord.ID
WHERE record.ID IN (SELECT ID FROM @ids)
我的第一个也是最明显的问题是,在每个选择条件中都有多余的代码(SELECT ID FROM @verifiedMasterRecordsIds)。如何重构才能避免冗余呢?另外,如果有更好的方法用这个逻辑从这个表中提取数据,我会很高兴看到。
这段代码只返回@ids变量中的记录。并选择依赖于@verifiedMasterRecordsIds变量中现有记录的字段。请写下我是否正确理解你
DECLARE @verifiedMasterRecordsIds [dbo].[Ints]
INSERT INTO @verifiedMasterRecordsIds
EXEC sp_getVerifiedMasterRecordsIds
;
SELECT record.ID, verRecord.Field1, verRecord.Field2, verRecord.Field3, verRecord.Field4
FROM Records as record
LEFT JOIN Records as verRecord ON record.VerifiedRecordID=verRecord.ID
WHERE record.ID IN (SELECT ID FROM @ids)
and record.ID IN (SELECT ID FROM @verifiedMasterRecordsIds)
union
SELECT ID, Field1, Field2, Field3, Field4
FROM Records as record
WHERE ID IN (SELECT ID FROM @ids)
and ID NOT IN (SELECT ID FROM @verifiedMasterRecordsIds);
如果没有例子,我觉得这个逻辑有点难以理解--所有这些id列表,你并不清楚你到底需要匹配哪些表来选择一个表或另一个表。
话说回来,如果你把值拆开,把表的逻辑移到下面,你的查询会更简单。FROM
条款。 这可能会达到你想要的目的。
SELECT r.ID, v.which,
COALESCE(v.verified_field, r._recordfield)
INTO #TempRecords
FROM Records r LEFT JOIN
@verifiedMasterRecordsIds vmr
ON vmr.id = r.id LEFT JOIN
Records vr
ON vr.ID = r.VerifiedRecordID AND vmr.id IS NOT NULL
(VALUES ('Field1', r.Field1, vr.Field1),
('Field2', r.Field2, vr.Field2),
('Field3', r.Field3, vr.Field3),
('Field4', r.Field4, vr.Field4)
) v(which, record_field, verified_field)
WHERE r.ID IN (SELECT i.ID FROM @ids i) ;
当然,你也可以把数据重新定位。
实际上,也许你只是想把条件移到下面的 FROM
分句 -- -- 不需要取消枢轴。
SELECT r.ID, v.which,
(CASE WHEN vrm.id IS NOT NULL THEN vr.Field1 ELSE r.Field1 END),
(CASE WHEN vrm.id IS NOT NULL THEN vr.Field2 ELSE r.Field2 END),
(CASE WHEN vrm.id IS NOT NULL THEN vr.Field3 ELSE r.Field3 END),
(CASE WHEN vrm.id IS NOT NULL THEN vr.Field4 ELSE r.Field4 END)
INTO #TempRecords
FROM Records r LEFT JOIN
@verifiedMasterRecordsIds vmr
ON vmr.id = r.id LEFT JOIN
Records vr
ON vr.ID = r.VerifiedRecordID
WHERE r.ID IN (SELECT i.ID FROM @ids i) ;