左连接的替代方案

Posted

技术标签:

【中文标题】左连接的替代方案【英文标题】:Alternative to Left Join 【发布时间】:2013-05-30 22:33:00 【问题描述】:

我需要使用 MS Query 在 Excel 2007 中显示一组固定管道的月费率,即使管道没有月费率,也必须以这种方式显示

我已在 SQL Server 2008 R2 中使用以下代码完成此操作。

SELECT P.Name     AS [Pipeline Name], 
       PR.Id, 
       PR.[Name], 
       PH.[Value] AS Rate 
FROM   [GAS].[dbo].[Pipelinerate] PR 
       INNER JOIN Pipeline P 
               ON P.Id = PR.Pipelineid 
       LEFT OUTER JOIN [GAS].[dbo].[Pipelineratehistory] PH 
               ON PH.[Pipelinerateid] = PR.[Id] 
               AND ( PH.[Month] = ?   --Month
                     AND PH.[Year] = ? )  --Year
WHERE  ( PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) ) 
       AND ISNULL(PH.Deprecated, 'n') <> 'Y' 
ORDER  BY [Pipeline name], 
          PR.[Name] 

当我尝试在 Excel 2007 的 MS Query 中执行此操作时,我得到以下错误

[Microsoft][ODBC SQL Server Driver] Invalid Parameter Number

[Microsoft][ODBC SQL Server Driver] Invalid Descriptor Index

我通过跟踪和错误发现,如果我从ON 子句中删除带有参数的条件并将其放入WHERE Clause 中,如下所示

SELECT P.Name     AS [Pipeline Name], 
       PR.Id, 
       PR.[Name], 
       PH.[Value] AS Rate 
FROM   [GAS].[dbo].[Pipelinerate] PR 
       INNER JOIN Pipeline P 
               ON P.Id = PR.Pipelineid 
       LEFT OUTER JOIN [GAS].[dbo].[Pipelineratehistory] PH 
               ON PH.[Pipelinerateid] = PR.[Id] 
WHERE  ( PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) ) 
       AND ( PH.[Month] = ?   --Month
             AND PH.[Year] = ? )  --Year
       AND ISNULL(PH.Deprecated, 'n') <> 'Y' 
ORDER  BY [Pipeline name], 
          PR.[Name] 

代码在 MS Query 中运行并给出以下结果

在此输出中,未显示当月没有费率的管道。因此,此代码不起作用。因此,在这种情况下,我试图找到LEFT JOIN 的替代品,以使用 MS Query 在 excel 中获得所需的输出。

协会 Pipeline 和 PipelineRate - 可选的一对多关系 PipelineRate 和 PipelineRateHistory - 可选的一对多关系

任何人都可以建议左加入的替代方法或实现此目的的方法吗?

PS:我不能使用存储过程。我知道如何使用 VBA 来做到这一点。我需要使用 MS Query 来完成此操作

【问题讨论】:

你的桌子上有什么关联? Pipeline和PipelineRate的关联是可选的一对多关系,PipelineRate和PipelineRateHistory的关联也是可选的一对多关系 【参考方案1】:

试试:

SELECT P.Name     AS [Pipeline Name], 
       PR.Id, 
       PR.[Name], 
       PH.[Value] AS Rate 
FROM   [GAS].[dbo].[Pipelinerate] PR 
       INNER JOIN Pipeline P 
               ON P.Id = PR.Pipelineid 
       LEFT OUTER JOIN [GAS].[dbo].[Pipelineratehistory] PH 
               ON PH.[Pipelinerateid] = PR.[Id] 
               AND PH.[Month] = ?   --Month
                     AND PH.[Year] = ? --Year
WHERE  ( PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) ) 
       AND ISNULL(PH.Deprecated, 'n') <> 'Y' 
ORDER  BY [Pipeline name], 
          PR.[Name] 

我所做的只是删除了一些不必要的括号。显然Excel有一个错误。解决方法之一是将其转换为存储过程并从 Excel 调用存储过程。从阅读来看,参数的确定和编号方式可能存在问题。

【讨论】:

我试过了,还是不行,报同样的错误。我没有创建存储过程的权限【参考方案2】:

也许只是 ODBC 未能成功地尝试重写您的查询。我不知道为什么ON 版本不起作用,但您只需在WHERE 中包含空值。 Nulls 不等同于任何东西,因此= 正在删除带有空值的行。

SELECT P.Name     AS [Pipeline Name], 
       PR.Id, 
       PR.[Name], 
       PH.[Value] AS Rate 
  FROM [GAS].[dbo].[Pipelinerate] PR 
 INNER JOIN Pipeline P 
    ON P.Id = PR.Pipelineid 
  LEFT OUTER JOIN [GAS].[dbo].[Pipelineratehistory] PH 
    ON PH.[Pipelinerateid] = PR.[Id] 
 WHERE PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) 
   AND ISNULL(PH.Deprecated, 'n') <> 'Y' 
   AND (PH.[Month] IS NULL OR
        (PH.[Month] = ?   --Month
     AND PH.[Year] = ? )  --Year
        )
ORDER  BY [Pipeline name], 
          PR.[Name] 

【讨论】:

我试过了,得到的结果与 WHERE 中没有空值的结果相同 我想我得到相同答案的原因是因为在联接中有其他月份的费率是匹配的,因此不返回空值【参考方案3】:

根据您的第一个查询,您尝试将月份过滤器放在左连接中。 因为那是一个左加入你获取记录的月份和年份过滤器不是强制性的。

但在下一个查询中,您将过滤器置于 where 条件中,因此查询不会为您返回任何结果。

如果您的月份和年份过滤器是强制性的,请将其放在第二个查询给出正确数量的结果的位置。

否则请使用此查询

SELECT P.Name     AS [Pipeline Name], 
       PR.Id, 
       PR.[Name], 
       PH.[Value] AS Rate 
FROM   [GAS].[dbo].[Pipelinerate] PR 
       INNER JOIN Pipeline P 
               ON P.Id = PR.Pipelineid 
       LEFT OUTER JOIN (select [Pipelinerateid],[Value] 
                       from [GAS].[dbo].[Pipelineratehistory] 
                       where [Month] = ?   --Month
                     AND [Year] = ? --Year
                      ) PH 
               ON PH.[Pipelinerateid] = PR.[Id] 
       WHERE  ( PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) ) 
               AND ISNULL(PH.Deprecated, 'n') <> 'Y' 
ORDER  BY [Pipeline name], 
          PR.[Name] 

【讨论】:

以上是关于左连接的替代方案的主要内容,如果未能解决你的问题,请参考以下文章

Querydsl:如何按列进行左连接

我想要左连接的解决方案来改善存储过程的结果

R语言进行dataframe数据左连接(Left join):使用R原生方法data.tabledplyr等方案

Hive - 具有左外连接的 OR 条件

左外连接和左连接一样吗? [复制]

在mysql查询中结合左连接和右连接