存储过程:查询优化

时间:2014-06-10 20:37:07

标签: sql-server performance stored-procedures

系统有一个存储过程,有7个选择并使用UNION将其联合起来。我已经优化但查询仍然很慢。

有没有办法更快地完成?

我尝试使用CASE更快地完成,但仍然很慢。执行时间是一分钟。

根据下面的查询,我应该创建哪些索引?

CODE

ALTER PROCEDURE [dbo].[USP_DEN_S_CONTROLE_DIARIO]
(
    @CLI_N_CODIGO NUMERIC(18),
    @DATA_CONSULTA DATETIME 
)
AS

DECLARE @DATA AS DATE = DBO.FUN_DEN_DATA_SEM_HORA(@DATA_CONSULTA)

SELECT DISTINCT
    PAC.PAC_N_CODIGO,
    PAC.PAC_C_NOME,
    PAC.PAC_C_MATRICULA,
    PAC.PAC_D_ULTIMA_VISITA,
    CASE ODO.ODO_PTR_N_CODIGO 
        WHEN 2 THEN 'S'
        WHEN 1 THEN 'N'
        ELSE 'N'
    END AS ORCAMENTO,
    CTR.CTR_C_CODINTELIGENTE,
    CTR.CTR_N_VALOR_RECEBIDO,
    (SELECT SUM(VIN_N_VALOR) FROM DEN_VIN_VINCULO_TRATAMENTO WHERE VIN_OXD_ODO_N_CODIGO = ODO_N_CODIGO) AS VALOR_ORC,

    CASE WHEN CTR.CTR_DET_N_CODIGO IS NULL THEN 
        (SELECT DET_C_NOME FROM DEN_DET_DENTISTA WHERE DET_N_CODIGO = PAC.PAC_DET_N_CODIGO AND DET_CLI_N_CODIGO = @CLI_N_CODIGO)
    ELSE    
        (SELECT DET_C_NOME FROM DEN_DET_DENTISTA WHERE DET_N_CODIGO = CTR.CTR_DET_N_CODIGO AND DET_CLI_N_CODIGO = @CLI_N_CODIGO)
    END AS DENTISTA,

    CASE WHEN ODO.ODO_PTR_N_CODIGO IS NULL AND CTR.CTR_N_VALOR_RECEBIDO IS NULL
    THEN
        CASE WHEN 
        (
        SELECT COUNT(*) FROM 
            DEN_VIN_VINCULO_TRATAMENTO INNER JOIN DEN_ODO_ODONTOGRAMA ON VIN_OXD_ODO_N_CODIGO = ODO_N_CODIGO 
        WHERE 
            ODO_PAC_N_CODIGO = PAC_N_CODIGO AND ODO_B_ATIVO = 1 
        AND
            (
                DBO.FUN_DEN_DATA_SEM_HORA(ODO_D_DATA_CADASTRO) = @DATA
            OR
                DBO.FUN_DEN_DATA_SEM_HORA(VIN_D_DATA_REALIZADO) = @DATA
            OR
                DBO.FUN_DEN_DATA_SEM_HORA(VIN_D_DATA_CADASTRO) = @DATA
            )
        ) = 0
        THEN
            '1'
        ELSE
            '0'
        END 
    ELSE
        '0'
    END AS SEM_AGENDAMENTO
FROM
    DEN_PAC_PACIENTE PAC
LEFT JOIN
    DEN_CTR_CONTA_RECEBER CTR ON (CTR.CTR_PAC_N_CODIGO = PAC.PAC_N_CODIGO) 
                              AND CTR.CTR_B_ATIVO = 1
                              AND (DBO.FUN_DEN_DATA_SEM_HORA(CTR.CTR_D_DATA_RECEBIMENTO) = @DATA)
LEFT JOIN
    DEN_ODO_ODONTOGRAMA ODO ON (ODO.ODO_N_CODIGO = CTR.CTR_ODO_N_CODIGO 
                                OR 
                                (ODO.ODO_PAC_N_CODIGO = PAC.PAC_N_CODIGO 
                                 AND 
                                 (ODO_B_APROVADO = 0 OR ODO_B_APROVADO IS NULL))
                                )
                            AND DBO.FUN_DEN_DATA_SEM_HORA(ODO.ODO_D_DATA_CADASTRO) = @DATA
WHERE
    PAC.PAC_B_ATIVO = 1
    AND DBO.FUN_DEN_DATA_SEM_HORA(PAC.PAC_D_ULTIMA_VISITA) = @DATA
    AND PAC.PAC_CLI_N_CODIGO = @CLI_N_CODIGO
ORDER BY
    PAC.PAC_D_ULTIMA_VISITA

1 个答案:

答案 0 :(得分:0)

您可以创建一个#temp表并将所有记录插入其中。我假设由于您使用的是Union,因此所有选择的查询都必须返回相同数量的coulmns且具有相同的数据类型。将记录插入临时表时不要使用union。最后,从临时表中选择*。

通过单独的选择查询将记录插入临时表将比7个联合选择查询更快。