【问题标题】:How to improve SQL query performance with a lot of inner selects?如何通过大量内部选择提高 SQL 查询性能?
【发布时间】:2021-01-22 20:30:45
【问题描述】:

如何更改此 SQL 查询以提高性能?

我需要根据EntityID (EntidadeID) 从客户、供应商或联系人中选择姓名、地址、电话等

  • EntidadeID = 1Clients 表中获取数据
  • EntidadeID = 2Supplier 表中获取数据
  • EntidadeID = 3Contacts 表中获取数据

SQL 代码:

CREATE VIEW [dbo].[View_AtivTecnicasAtivTecnicasMatSer]
AS
    SELECT        
        a.Numero, a.UserFullName, a.Data, a.Hora, a.CodigoTerceiro, 
        a.Contacto, a.Tarefa, a.UserTarefaNome, a.AFaturar, a.Resolvido, 
        a.AgendadaData, a.AgendadaHora, a.AlertaData, a.AlertaHora, 
        a.Execucao, a.NotasInternas, a.ResolvidoData, a.ResolvidoHora, 
        a.ResolvidoUserFullName, a.NumeroAtendInicial, a.EmailCliente, 
        a.EmailUserTarefa, a.PDFTarefaAnexo, a.DataNotifInformativa, 
        a.DataNotifResolucao, a.TipoDoc, a.UserTarefaAlertado, 
        a.Origem, a.Anulado, a.TotalSIVA, a.TotalCIVA, a.Moeda, a.Cambio, 
        a.TaxaDesconto, a.TipoPreco, dbo.WR_Temas.Descricao, 
        CASE 
           WHEN EntidadeID = 1 THEN
                             (SELECT        Descricao
                               FROM            dbo.WR_ClientesEstab
                               WHERE        ID = a.ClienteEstabID) 
        END AS Estab, 
        CASE 
           WHEN a.EntidadeID = 1 THEN
                             (SELECT        Morada
                               FROM            dbo.WR_ClientesEstab
                               WHERE        ID = a.ClienteEstabID) 
           WHEN a.EntidadeID = 2 THEN
                             (SELECT        Morada
                               FROM            dbo.WR_Fornecedores
                               WHERE        Codigo = a.CodigoTerceiro) 
        END AS Morada, 
        CASE 
           WHEN a.EntidadeID = 1 THEN
                             (SELECT        Localidade
                               FROM            dbo.WR_ClientesEstab
                               WHERE        ID = a.ClienteEstabID) 
           WHEN a.EntidadeID = 2 THEN
                             (SELECT        Localidade
                               FROM            dbo.WR_Fornecedores
                               WHERE        Codigo = a.CodigoTerceiro) 
        END AS Localidade, 
        CASE 
           WHEN a.EntidadeID = 1 THEN
                             (SELECT        CodPostal
                               FROM            dbo.WR_ClientesEstab
                               WHERE        ID = a.ClienteEstabID) 
           WHEN a.EntidadeID = 2 THEN
                             (SELECT        CodPostal
                               FROM            dbo.WR_Fornecedores
                               WHERE        Codigo = a.CodigoTerceiro) 
        END AS CodPostal, CASE WHEN a.EntidadeID = 1 THEN
                             (SELECT        Telefone
                               FROM            dbo.WR_ClientesEstab
                               WHERE        ID = a.ClienteEstabID) END AS TelefoneEstab, CASE WHEN a.EntidadeID = 1 THEN
                             (SELECT        Telemovel
                               FROM            dbo.WR_ClientesEstab
                               WHERE        ID = a.ClienteEstabID) END AS TelemovelEstab, CASE WHEN a.EntidadeID = 1 THEN
                             (SELECT        Nome
                               FROM            dbo.WR_Clientes
                               WHERE        Codigo = a.CodigoTerceiro) WHEN a.EntidadeID = 2 THEN
                             (SELECT        Empresa
                               FROM            dbo.WR_Contactos
                               WHERE        ID = a.TerceiroID) WHEN a.EntidadeID = 3 THEN
                             (SELECT        Nome
                               FROM            dbo.WR_Fornecedores
                               WHERE        Codigo = a.CodigoTerceiro) END AS NomeTerceiro, CASE WHEN a.EntidadeID = 1 THEN
                             (SELECT        Telefone
                               FROM            dbo.WR_Clientes
                               WHERE        Codigo = a.CodigoTerceiro) WHEN a.EntidadeID = 2 THEN
                             (SELECT        Telefone
                               FROM            dbo.WR_Contactos
                               WHERE        ID = a.TerceiroID) WHEN a.EntidadeID = 3 THEN
                             (SELECT        Telefone
                               FROM            dbo.WR_Fornecedores
                               WHERE        Codigo = a.CodigoTerceiro) END AS Telefone, CASE WHEN a.EntidadeID = 1 THEN
                             (SELECT        Telemovel
                               FROM            dbo.WR_Clientes
                               WHERE        Codigo = a.CodigoTerceiro) WHEN a.EntidadeID = 2 THEN
                             (SELECT        Telemovel
                               FROM            dbo.WR_Contactos
                               WHERE        ID = a.TerceiroID) WHEN a.EntidadeID = 3 THEN
                             (SELECT        Telemovel
                               FROM            dbo.WR_Fornecedores
                               WHERE        Codigo = a.CodigoTerceiro) END AS Telemovel, CASE WHEN a.EntidadeID = 1 THEN
                             (SELECT        Contribuinte
                               FROM            dbo.WR_Clientes
                               WHERE        Codigo = a.CodigoTerceiro) WHEN a.EntidadeID = 2 THEN
                             (SELECT        Contribuinte
                               FROM            dbo.WR_Contactos
                               WHERE        ID = a.TerceiroID) WHEN a.EntidadeID = 3 THEN
                             (SELECT        Contribuinte
                               FROM            dbo.WR_Fornecedores
                               WHERE        Codigo = a.CodigoTerceiro) END AS Contribuinte, m.Linha, m.ArtigoCod, m.ArtigoDesc, m.Qtd, m.UN, m.ValorUnitario, m.DescontoPercentual, m.DescontoValor, m.Armazem, m.NumSerie, m.AnoERP, m.SerieERP, 
                         m.TipoDocERP, m.NumDocERP, m.DataExportadoERP, m.UserExportouERP, m.TaxaIva, m.TotalDescontos AS TotalDescontosLinha, m.TotalGeral AS TotalGeralLinhas, m.Ordenacao, m.ExportadaERP, m.DocERP, 
                         m.DescontoPercentual2, m.DescontoPercentual3, a.TotalMercadoria, a.TotalLiquido, a.TotalIVA, a.TotalGeral, a.TotalGeralEuros, a.TotalDescontosLinhas, a.TotalDescontosGlobal, a.TotalDescontos, a.EntidadeID, 
                         m.DescontoPercentual4
FROM            dbo.WR_AtivTecnicas AS a INNER JOIN
                         dbo.WR_Temas ON a.TemaID = dbo.WR_Temas.ID INNER JOIN
                         dbo.WR_AtivTecnicasMatSer AS m ON a.Numero = m.NumeroAtiv
GO

我尝试只制作包含所有字段的 3 个 Select Cases,但没有成功。

【问题讨论】:

  • 改为使用左连接。
  • 如果没有您的数据库模型(表、键、索引等),就无法提供帮助。一些调查提示:重新考虑您的数据库模型、使用联合表、使用索引、使用执行单独查询而不是庞大查询的脚本来拆分复杂性。
  • 请在代码问题中给出minimal reproducible example--包括剪切、粘贴和可运行的最小代码和以代码形式给出的最小代表性数据。对于包含 DBMS 和 DDL 的 SQL,包括约束、索引和表格初始化。对于包括 EXPLAIN 结果和统计信息的 SQL 性能。请研究和总结。对于包括优化/性能基础的 SQL——立即导致索引、计划、统计和 SARGability。 Tips for asking a good SQL question 在您学习并应用了这些基础知识后,请重新优化。 How to Ask

标签: sql performance select subquery case


【解决方案1】:

你需要做这样的事情: 正如@jarlh 提到的,你可以用左连接替换你的选择,因为你有这些规则:

EntidadeID = 1 gets data from Clients table
EntidadeID = 2 gets data from Supplier table
EntidadeID = 3 gets data from Contacts table

您可以将它们包含在您的加入条件中,这样您就可以完全删除案例,如下例所示:

SELECT
    *
     -- instead of case for example for Telemovel
    , COALESCE( ct.Telemovel, st.Telemovel, cts.Telemovel)
    -- replace all the case statements following above logic
FROM
    dbo.WR_AtivTecnicas                  AS A
    INNER JOIN dbo.WR_Temas
        ON A.TemaID = dbo.WR_Temas.ID
    INNER JOIN dbo.WR_AtivTecnicasMatSer AS m
        ON A.Numero = m.NumeroAtiv
    LEFT OUTER JOIN ClientsTable ct
      ON  ct.Codigo = a.CodigoTerceiro -- replace with proper condition
      AND EntidadeID = 1
    LEFT OUTER JOIN SupplierTable st
      ON  st.id = A.id  -- replace with proper condition
      AND EntidadeID = 2
    LEFT OUTER JOIN ContactsTable cts
      ON  cts.ID = a.TerceiroID  -- replace with proper condition 
      AND EntidadeID = 3

【讨论】:

    猜你喜欢
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    相关资源
    最近更新 更多