You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带WHERE条件的UNION ALL异常:存储过程返回重复行问题排查

存储过程重复结果问题及解决方案

问题背景

我有一个接收表类型参数的存储过程CheckPolicy,核心逻辑是检查Payment表中是否存在对应账户:存在返回VALID,不存在返回INVALID。但由于Payment表中PolicyNumber存在重复值,当前存储过程会返回多条重复的VALID记录,不符合每个账户仅返回一行的预期。我尝试将最终查询改为SELECT DISTINCT CorrectAccount, PolicyStatus FROM #TempReferencIds,请问该方案是否正确?

相关代码与数据

存储过程与表类型定义

CREATE PROCEDURE [dbo].[CheckPolicy]    
    @SearchAccount AS dbo.PayerSwapType READONLY    
AS  
BEGIN  
    SET NOCOUNT ON;  
  
    CREATE TABLE #TempReferencIds
    (
        CorrectAccount nvarchar(20),
        PolicyStatus nvarchar(10),
    )

    INSERT INTO #TempReferencIds (CorrectAccount, PolicyStatus)
        SELECT t.CorrectAccount, 'VALID' 
        FROM [dbo].Payment a 
        JOIN @SearchAccount t ON a.PolicyNumber = t.CorrectAccount

        UNION ALL
    
        SELECT t.CorrectAccount, 'INVALID' 
        FROM [dbo].Payment a 
        RIGHT JOIN @SearchAccount t ON a.PolicyNumber = t.CorrectAccount
        WHERE a.PolicyNumber IS NULL

    SELECT CorrectAccount, PolicyStatus 
    FROM #TempReferencIds
END

CREATE TYPE dbo.PayerSwapType AS TABLE
(
     CorrectAccount VARCHAR(20) NOT NULL
);

Payment表数据(PolicyNumber可重复)

PolicyNumber           AccountNumber
--------------------------------------------
7003741019             ljksdahfkjA9992
7003723876             101100QTGRWI1499
7003723876             201100QTGRWI1499
7003741001             63e190SSSIUU0075
7003741001             60ds190SSSIUU0075
7003740987             601s90SSSIUU0075
7003740987             601s90SSSIUU0075
7003740987             601h90SSSIUU0075

当前返回结果

CorrectAccount  PolicyStatus
---------------------------
7003741019      VALID
7003723876      VALID
7003723876      VALID
7003741001      VALID
7003741001      VALID
7003740987      VALID
7003740987      VALID
7003740987      VALID
213786777       INVALID

预期返回结果

CorrectAccount   PolicyStatus
-----------------------------
7003741019       VALID
7003723876       VALID
7003741001       VALID
7003740987       VALID
213786777        INVALID

输入参数

7003741019
7003723876
7003741001
7003740987
213786777

修改后的查询语句

select distinct CorrectAccount, PolicyStatus
from #TempReferencIds  

解决方案分析

原修改方案的正确性

你提出的SELECT DISTINCT方案是正确的。DISTINCT关键字会对结果集去重,确保每个CorrectAccount只返回一行对应的PolicyStatus,完全符合你的预期结果。

更高效的优化方案

虽然DISTINCT能解决问题,但原存储过程先插入大量重复数据到临时表再去重,存在不必要的IO开销。可以直接通过一次查询完成判断,避免生成重复数据,性能更优:

CREATE PROCEDURE [dbo].[CheckPolicy]    
    @SearchAccount AS dbo.PayerSwapType READONLY    
AS  
BEGIN  
    SET NOCOUNT ON;  

    SELECT 
        t.CorrectAccount,
        CASE WHEN EXISTS (SELECT 1 FROM [dbo].Payment a WHERE a.PolicyNumber = t.CorrectAccount)
             THEN 'VALID'
             ELSE 'INVALID'
        END AS PolicyStatus
    FROM @SearchAccount t
END

或者使用LEFT JOIN结合DISTINCT(不过EXISTS通常性能更优):

CREATE PROCEDURE [dbo].[CheckPolicy]    
    @SearchAccount AS dbo.PayerSwapType READONLY    
AS  
BEGIN  
    SET NOCOUNT ON;  

    SELECT DISTINCT
        t.CorrectAccount,
        CASE WHEN a.PolicyNumber IS NOT NULL THEN 'VALID' ELSE 'INVALID' END AS PolicyStatus
    FROM @SearchAccount t
    LEFT JOIN [dbo].Payment a ON a.PolicyNumber = t.CorrectAccount
END

这两种方案都不需要临时表,直接从输入参数表和Payment表关联判断,一次性得到每个账户的状态,避免了先插入重复数据再去重的冗余步骤,执行效率更高。

内容的提问来源于stack exchange,提问作者user17824023

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:38:31