当第一个选择不总是返回特定行的值时,如何将一个选择与另一个选择连接?

时间:2015-06-23 23:08:31

标签: sql-server join union

我有一个复杂的查询来检索一些结果:

EDITED QUERY(添加了UNION ALL):

MEDIA_ROOT = path.join(PROJECT_ROOT, 'media').replace('\\', '/')

MEDIA_URL = 'https://my_site.blob.core.windows.net/'

结果如下:Query 1

它工作得很好,问题是我被问到如果这个查询中没有一行,它必须包含来自另一个表(ServicoAreaTecnica)的值,所以我根据关键信息得到了另一个表的查询第一个查询。所以如果我UNION ALL我得到了这个:

SELECT  t.*
FROM (

    SELECT  
        dbo.Intervencao.INT_Processo, analista, 
        ETS.ETS_Sigla, ATC.ATC_Sigla, PAT.PAT_Sigla, dbo.Assunto.SNT_Peso,
        CASE 
            WHEN ETS.ETS_Sigla = 'PE' AND (PAT.PAT_Sigla = 'LIB' OR PAT.PAT_Sigla = 'LBR') THEN (0.3*SNT_Peso) 
            WHEN ETS.ETS_Sigla = 'CD' THEN (0.3*SNT_Peso)*0.3  
            ELSE SNT_Peso
        END AS PESOAREA,
        CASE 
            WHEN a.max_TEA_FimTarefa IS NULL THEN a.max_TEA_InicioTarefa
            ELSE a.max_TEA_FimTarefa
        END AS DATA_INICIO_TERMINO,
        ROW_NUMBER() OVER (PARTITION BY ATC.ATC_Sigla, a.SRV_Id ORDER BY TEA_FimTarefa DESC) AS seqnum 
    FROM dbo.Tarefa AS t

    INNER JOIN (
        SELECT 
            MAX(dbo.TarefaEtapaAreaTecnica.TEA_InicioTarefa) AS max_TEA_InicioTarefa,
            MAX (dbo.TarefaEtapaAreaTecnica.TEA_FimTarefa) AS max_TEA_FimTarefa,
            dbo.Pessoa.PFJ_Descri AS analista, dbo.AreaTecnica.ATC_Id, dbo.Tarefa.SRV_Id
        FROM dbo.TarefaEtapaAreaTecnica 
        LEFT JOIN dbo.Tarefa ON dbo.TarefaEtapaAreaTecnica.TRF_Id = dbo.Tarefa.TRF_Id
        LEFT JOIN dbo.AreaTecnica ON dbo.TarefaEtapaAreaTecnica.ATC_Id = dbo.AreaTecnica.ATC_Id 
        LEFT JOIN dbo.ServicoAreaTecnica ON dbo.TarefaEtapaAreaTecnica.ATC_Id = dbo.ServicoAreaTecnica.ATC_Id 
            AND dbo.Tarefa.SRV_Id = dbo.ServicoAreaTecnica.SRV_Id
        INNER JOIN dbo.Pessoa ON dbo.Pessoa.PFJ_Id = dbo.ServicoAreaTecnica.PFJ_Id_Analista
        GROUP BY dbo.AreaTecnica.ATC_Id, dbo.Tarefa.SRV_Id, dbo.Pessoa.PFJ_Descri
    ) AS a ON t.SRV_Id = a.SRV_Id

    INNER JOIN dbo.TarefaEtapaAreaTecnica AS TarefaEtapaAreaTecnica_1 ON 
        t.TRF_Id = TarefaEtapaAreaTecnica_1.TRF_Id 
        AND a.ATC_Id = TarefaEtapaAreaTecnica_1.ATC_Id 
        AND a.max_TEA_InicioTarefa = TarefaEtapaAreaTecnica_1.TEA_InicioTarefa
    LEFT JOIN AreaTecnica ATC ON TarefaEtapaAreaTecnica_1.ATC_Id = ATC.ATC_Id
    LEFT JOIN Etapa ETS ON TarefaEtapaAreaTecnica_1.ETS_Id = ETS.ETS_Id
    LEFT JOIN ParecerTipo PAT ON TarefaEtapaAreaTecnica_1.PAT_Id = PAT.PAT_Id
    LEFT OUTER JOIN dbo.Servico ON a.SRV_Id = dbo.Servico.SRV_Id
    INNER JOIN dbo.Intervencao ON dbo.Servico.INT_Id = dbo.Intervencao.INT_Id
    LEFT JOIN dbo.Assunto ON dbo.Servico.SNT_Id = dbo.Assunto.SNT_Id

) t

结果如下:enter image description here

所以我要做的是删除第1行,因为第一个查询中存在第2行,我想我这次解释得更好了。结果应该只是第1行,只有当查询1没有为该特定INN.INT_Processo检索行时,才会出现第2行。

谢谢!

enter image description here

3 个答案:

答案 0 :(得分:1)

你的代码难以阅读,因为所有内容的名称都很冗长(说实话,他们使用我不会说的语言也会让事情变得更加困难)。

但是如何:用INNER JOIN替换LEFT JOIN s,在替代表中添加更多LEFT JOIN s,并为每个变量引入ISNULL子句想要在结果中?

答案 1 :(得分:1)

好的,有两种方法可以减少您的记录集。鉴于您已经编写了代码来生成带有额外行的表,最简单的方法是添加代码来减少这些:

Select * from 
    (Select *
      , Row_Number() over 
           (partition by IntProcesso, Analista order by ISNULL(seqnum, 0) desc) as RN
    from MyResults) a
where RN = 1

这会将row_number 1分配给来自第一个查询的任何行,或者分配给第二个查询中第一个查询中没有匹配项的任何行,然后过滤掉额外的行。

您也可以使用isnullcoalesce的外部联接,正如其他人所建议的那样。像这样:

Select ISNULL(a.IntProcesso, b.IntProcesso) as IntProcesso
    , ISNULL(a.Analista, b.Analista) as Analista
    , ISNULL(a.ETSsigla, b.ETSsigla) as ETSsigla
    [repeat for the rest of your columns]
from Table1 a
full outer join Table2 b
on a.IntProcesso = b.IntProcesso and a.Analista = b.Analista

答案 2 :(得分:0)

如果您执行... Query1 Right Join Query2 On ...之类的操作,则应该只获取Query2中不会出现在查询1中的行。

相关问题