【问题标题】:How to remove redundant code from SQL conditional query如何从 SQL 条件查询中删除冗余代码
【发布时间】:2020-05-24 07:59:56
【问题描述】:

我有以下情况。

我得到了一些经过验证的、未经验证的记录和(比如说)主验证记录的表格。编辑:在表中,我得到了标准的唯一 ID 字段,但还有一个名为 VerifiedRecordID 的列指向表中的其他记录,或者它为 NULL。

如果记录的 VerifiedRecordID = NULL,则为未验证记录。

如果记录有 VerifiedRecordID = some_id,那么这条记录是经过验证的,并且

ID=some_id 是主验证的记录。

许多验证记录可能指向一个主验证记录。最后一个只是为了提供经过验证的记录和经过验证的数据,不能直接访问。

但是还有另一个因素决定记录是否被验证,不仅仅是这个字段,所以验证是由存储过程决定的。因此,如果您访问未验证的记录,它将返回其字段。如果您访问经过 IS 验证的记录,它将忽略其字段(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)。如何对其进行重构以避免冗余? 另外,如果有更好的方法可以用这种逻辑从这个表中提取数据,我会很高兴看到它。

【问题讨论】:

  • 如果ID 是唯一的,则外连接@verifiedMasterRecordsIds
  • ID 字段是唯一的。问题已编辑。
  • 使用LEFT JOIN @verifiedMasterRecordsIds
  • 什么是#TempRecords 表?为什么它与 CTE 中的 INTO 语句一致?
  • #TempRecords 稍后将用于进一步查询。可能与当前问题无关。

标签: sql sql-server redundancy


【解决方案1】:

此代码仅返回 @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);

【讨论】:

  • 我还是不明白@ids 变量从何而来
  • "...所以,我想创建一个存储过程,通过传递的@ids 参数从表中提取记录,该参数可能包含已验证或未验证记录的 id(但不是主验证记录,因为它们不能直接访问)....”
  • @ids 是否包含一条记录或者这是一张表?
  • 听起来像是 ids 列表。
【解决方案2】:

如果没有示例,我发现逻辑有点难以理解——所有这些 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) ;

【讨论】:

  • @ids 是约束 ID 字段的参数。 ID 字段是唯一的主键。 VerifiedRecordID 是同一个表的外键。我知道逻辑不是那么简单,而是项目的目的所需要的。另外,我的 SQL 很差,所以无法理解和验证您的答案的正确性。我的SQL知识很差,对不起!
猜你喜欢
  • 1970-01-01
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-13
  • 2016-08-02
  • 1970-01-01
相关资源
最近更新 更多